Класс Thread в Java
Класс Thread — это основной класс в Java для создания потоков и управления ими.
В Java каждый поток является экземпляром класса Thread. Поток можно понимать как независимо выполняемую «подзадачу» в программе, что позволяет программе выполнять несколько операций одновременно.
В Java есть два способа создания потоков:
- Наследовать класс Thread
- Реализовать интерфейс Runnable
Базовое использование класса Thread
Создание потоков
Пример
class MyThread extends Thread {
public void run() {
System.out.println("Поток выполняется");
}
}
// Способ 2: Реализовать интерфейс Runnable
class MyRunnable implements Runnable {
public void run() {
System.out.println("Поток выполняется");
}
}
public class Main {
public static void main(String[] args) {
// Использование подхода с наследованием
MyThread thread1 = new MyThread();
thread1.start();
// Использование подхода с интерфейсом
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
}
}
Жизненный цикл потока
Потоки Java имеют следующие состояния:
- NEW: Только что созданный поток, метод start() еще не был вызван
- RUNNABLE: Состояние готовности к выполнению, может выполняться или ожидать процессорного времени
- BLOCKED: Поток заблокирован, ожидает получения блокировки монитора
- WAITING: Состояние ожидания, при котором поток ждет выполнения другими потоками определенных операций
- TIMED_WAITING: Состояние ожидания с тайм-аутом
- TERMINATED: Поток завершен
Общие методы класса Thread
Базовые методы управления
Пример
System.out.println("Поток выполняется");
});
thread.start(); // Запустить поток
thread.join(); // Дождаться завершения потока
thread.sleep(1000); // Поток спит 1 секунду
Приоритет потока
Пример
thread.setPriority(Thread.NORM_PRIORITY); // Приоритет по умолчанию (5)
thread.setPriority(Thread.MIN_PRIORITY); // Наименьший приоритет (1)
Прерывание потоков
Пример
// Проверить статус прерывания в потоке
if (Thread.interrupted()) {
// Обработать логику прерывания
}
Синхронизация потоков
Когда несколько потоков обращаются к общим ресурсам, необходимо использовать механизмы синхронизации, чтобы избежать проблем с несогласованностью данных.
Использование ключевого слова synchronized
Пример
private int count = 0;
public synchronized void increment() {
count++;
}
}
Использование интерфейса Lock
Пример
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private int count = 0;
private Lock lock = new ReentrantLock();
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
Пул потоков и класс Thread
В реальной разработке пулы потоков обычно используются для управления потоками, а не для прямого создания объектов Thread.
Пример
import java.util.concurrent.Executors;
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
executor.execute(() -> {
System.out.println("Поток выполняет задачу");
});
}
executor.shutdown();
}
}
Лучшие практики
- Предпочитайте создавать потоки, реализуя интерфейс Runnable
- Используйте пулы потоков для управления ресурсами потоков
- Избегайте чрезмерной синхронизации; используйте механизмы синхронизации только при необходимости
- Используйте ключевое слово volatile для обеспечения видимости переменной
- Рассмотрите возможность использования расширенных служебных классов в пакете параллелизма Java (java.util.concurrent)
Разумно используя класс Thread и связанные инструменты параллелизма, можно писать эффективные и надёжные многопоточные программы на Java.
Дополнительные расширения