← Назад к вопросам

Что такое поток?

1.0 Junior🔥 201 комментариев
#Многопоточность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Поток (Thread) в Java

Поток (Thread) — это легковесный процесс выполнения кода, который представляет последовательность инструкций, выполняемых независимо в рамках одного процесса. Потоки позволяют программе выполнять несколько задач одновременно (параллельно), делая приложение более отзывчивым и эффективным.

Основные понятия

Процесс vs Поток:

  • Процесс — самостоятельная программа с собственной памятью, запущенная на ОС
  • Поток — подразделение процесса, разделяет память процесса с другими потоками
Операционная система
└── Процесс (MyApp)
    ├── Main Thread
    ├── Worker Thread 1
    ├── Worker Thread 2
    └── Worker Thread 3

Создание потока

1. Наследование класса Thread

public class MyThread extends Thread {
    private String name;
    
    public MyThread(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {  // Реализуем метод run()
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " - Iteration " + i);
            try {
                Thread.sleep(1000);  // Пауза на 1 секунду
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    public static void main(String[] args) {
        // Создаем потоки
        MyThread thread1 = new MyThread("Thread-1");
        MyThread thread2 = new MyThread("Thread-2");
        
        // Запускаем потоки
        thread1.start();  // Вызываем start(), не run()!
        thread2.start();
        
        System.out.println("Main thread continues...");
    }
}

// Вывод (порядок может отличаться):
// Main thread continues...
// Thread-1 - Iteration 0
// Thread-2 - Iteration 0
// Thread-1 - Iteration 1
// Thread-2 - Iteration 1
// ...

2. Реализация интерфейса Runnable (предпочтительно)

public class MyRunnable implements Runnable {
    private String name;
    
    public MyRunnable(String name) {
        this.name = name;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " - Iteration " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }
    }
    
    public static void main(String[] args) {
        // Создаем потоки
        Thread thread1 = new Thread(new MyRunnable("Thread-1"));
        Thread thread2 = new Thread(new MyRunnable("Thread-2"));
        
        thread1.start();
        thread2.start();
    }
}

// Или с lambda (Java 8+)
Thread thread1 = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("Thread " + i);
    }
});
thread1.start();

Жизненный цикл потока

┌─────────────┐
│   NEW       │  Thread создан, но еще не запущен
└──────┬──────┘
       │ thread.start()
       ▼
┌─────────────────────┐
│   RUNNABLE          │  Поток готов к выполнению
│   (READY)           │  (может ждать в очереди)
└──────┬──────────────┘
       │ ОС выделяет процессорное время
       ▼
┌─────────────┐
│   RUNNING   │  Поток выполняется
└──────┬──────┘
       │ Различные события
       ├─────────────────────────┐
       │                         │
       ▼                         ▼
┌──────────────┐      ┌──────────────────┐
│   WAITING    │      │   BLOCKED/TIMED  │
│ (wait/join)  │      │ (lock/sleep)     │
└──────┬───────┘      └────────┬─────────┘
       │                       │
       └───────────┬───────────┘
                   ▼
       ┌─────────────────────┐
       │   RUNNABLE (READY)  │
       └──────┬──────────────┘
              │
              ▼
       ┌──────────────┐
       │  TERMINATED  │  run() завершился
       └──────────────┘

Состояния потока (Thread States)

public class ThreadStateExample {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread started, state: " + 
                    Thread.currentThread().getState());  // RUNNABLE
                Thread.sleep(2000);  // TIMED_WAITING
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        System.out.println("Before start: " + thread.getState());  // NEW
        thread.start();
        System.out.println("After start: " + thread.getState());   // RUNNABLE
        
        Thread.sleep(1000);
        System.out.println("During sleep: " + thread.getState());  // TIMED_WAITING
        
        thread.join();  // Ожидаем завершения
        System.out.println("After join: " + thread.getState());    // TERMINATED
    }
}

Важные методы Thread

1. sleep() — временная пауза

try {
    Thread.sleep(1000);  // Пауза на 1 секунду
} catch (InterruptedException e) {
    System.out.println("Sleep interrupted");
}

2. join() — ожидание завершения потока

Thread thread = new Thread(() -> {
    try {
        Thread.sleep(3000);
        System.out.println("Thread finished");
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
});

thread.start();
thread.join();  // Основной поток ждет завершения thread
System.out.println("Main continues after thread");

3. interrupt() — прерывание потока

Thread thread = new Thread(() -> {
    try {
        for (int i = 0; i < 10; i++) {
            System.out.println("i = " + i);
            Thread.sleep(1000);
        }
    } catch (InterruptedException e) {
        System.out.println("Thread was interrupted");
        Thread.currentThread().interrupt();  // Устанавливаем флаг
    }
});

thread.start();
Thread.sleep(3500);
thread.interrupt();  // Прерываем поток

4. getName(), setName() — имя потока

Thread thread = new Thread("MyWorker");
System.out.println(thread.getName());  // MyWorker
thread.setName("UpdatedWorker");
System.out.println(thread.getName());  // UpdatedWorker

5. getPriority(), setPriority() — приоритет

Thread thread = new Thread(() -> {
    System.out.println("Priority: " + Thread.currentThread().getPriority());
});

thread.setPriority(Thread.MAX_PRIORITY);    // 10
thread.setPriority(Thread.NORM_PRIORITY);   // 5
thread.setPriority(Thread.MIN_PRIORITY);    // 1
thread.start();

6. isAlive() — проверка статуса

Thread thread = new Thread(() -> {
    try { Thread.sleep(2000); } catch (InterruptedException e) {}
});

System.out.println(thread.isAlive());  // false
thread.start();
System.out.println(thread.isAlive());  // true
try { thread.join(); } catch (InterruptedException e) {}
System.out.println(thread.isAlive());  // false

Практический пример: многопоточность

public class MultiThreadExample {
    static class Counter {
        int count = 0;
        
        synchronized void increment() {  // Синхронизация для потокобезопасности
            count++;
            System.out.println(Thread.currentThread().getName() + ": " + count);
        }
    }
    
    public static void main(String[] args) throws InterruptedException {
        Counter counter = new Counter();
        
        // Создаем 3 потока
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                counter.increment();
            }
        }, "Thread-1");
        
        Thread thread2 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                counter.increment();
            }
        }, "Thread-2");
        
        Thread thread3 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                counter.increment();
            }
        }, "Thread-3");
        
        // Запускаем потоки
        thread1.start();
        thread2.start();
        thread3.start();
        
        // Ожидаем завершения всех потоков
        thread1.join();
        thread2.join();
        thread3.join();
        
        System.out.println("Final count: " + counter.count);  // 15
    }
}

Daemon потоки

Thread daemonThread = new Thread(() -> {
    while (true) {
        System.out.println("Daemon working...");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
});

daemonThread.setDaemon(true);  // Установить как daemon
daemonThread.start();

Thread.sleep(5000);
// Основной поток завершается, daemon потоки убиваются автоматически

Преимущества многопоточности

  • Отзывчивость — приложение не "зависает" на долгих операциях
  • Параллелизм — использование нескольких ядер процессора
  • Производительность — пока один поток ждет I/O, другие могут работать
  • Модульность — разделение логики на независимые потоки

Вызовы многопоточности

  • Race conditions — конфликты при доступе к общим данным
  • Deadlock — взаимная блокировка потоков
  • Сложность отладки — недетерминированное поведение

Потоки — это основа асинхронного программирования в Java и необходимы для создания отзывчивых, высокопроизводительных приложений.