Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Поток (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 и необходимы для создания отзывчивых, высокопроизводительных приложений.