Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Ответ
Как запустить поток в Java
В Java существует несколько способов создания и запуска потоков. Рассмотрим все основные подходы.
1. Использование Thread класса
Способ 1: Наследование от Thread
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(name + ": " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
}
}
}
public class Main {
public static void main(String[] args) {
Thread thread1 = new MyThread("Thread-1");
Thread thread2 = new MyThread("Thread-2");
// Запуск потоков
thread1.start();
thread2.start();
System.out.println("Main thread continues");
}
}
Способ 2: Реализация интерфейса Runnable
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 + ": " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Thread interrupted");
}
}
}
}
public class Main {
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();
}
}
Способ 3: Lambda выражения (Java 8+)
public class Main {
public static void main(String[] args) {
Thread thread1 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread-1: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 5; i++) {
System.out.println("Thread-2: " + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
thread1.start();
thread2.start();
}
}
2. Использование ExecutorService (рекомендуется)
Для управления пулом потоков лучше использовать ExecutorService:
import java.util.concurrent.*;
public class ExecutorExample {
public static void main(String[] args) {
// Создаём пул из 3 потоков
ExecutorService executor = Executors.newFixedThreadPool(3);
// Запускаем задачи
for (int i = 1; i <= 5; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " started by " + Thread.currentThread().getName());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("Task " + taskId + " completed");
});
}
// Завершаем работу
executor.shutdown();
try {
if (!executor.awaitTermination(10, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
}
3. Разные типы ExecutorService
// Пул с фиксированным числом потоков
ExecutorService fixed = Executors.newFixedThreadPool(4);
// Пул с одним потоком (последовательное выполнение)
ExecutorService single = Executors.newSingleThreadExecutor();
// Кешированный пул (растёт и сжимается по необходимости)
ExecutorService cached = Executors.newCachedThreadPool();
// Пул с графиком выполнения (ScheduledExecutorService)
ScheduledExecutorService scheduled = Executors.newScheduledThreadPool(2);
scheduled.scheduleAtFixedRate(() -> {
System.out.println("Task executed every 2 seconds");
}, 0, 2, TimeUnit.SECONDS);
4. Важные правила
ВСЕГДА используй start(), а не run():
Thread thread = new Thread(() -> System.out.println("Hello"));
// ✅ ПРАВИЛЬНО - создаёт новый поток
thread.start();
// ❌ НЕПРАВИЛЬНО - выполняется в текущем потоке
thread.run();
5. Установка приоритета потока
Thread thread = new Thread(() -> {
System.out.println("Running with priority " + Thread.currentThread().getPriority());
});
thread.setPriority(Thread.MAX_PRIORITY); // 10
thread.start();
6. Практический пример с обработкой
public class ThreadManagementExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(2);
for (int i = 1; i <= 4; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Task " + taskId + " started");
try {
Thread.sleep((long) (Math.random() * 3000));
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("Task " + taskId + " was interrupted");
}
System.out.println("Task " + taskId + " completed");
});
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
System.out.println("All tasks completed");
}
}
Сравнение подходов
| Способ | Преимущества | Недостатки | Когда использовать |
|---|---|---|---|
| Thread расширение | Простой старт | Нельзя наследовать другой класс | Редко (не рекомендуется) |
| Runnable | Можно наследовать другой класс | Немного сложнее | Иногда, для простых случаев |
| ExecutorService | Управление пулом, масштабируемость | Немного сложнее | Всегда в production |
| Lambda (Java 8+) | Компактно, современно | Требует Java 8+ | В современных проектах |
Ключевые выводы
- start() — создаёт новый поток
- run() — выполняет в текущем потоке (не используй!)
- ExecutorService — предпочтительный способ в production
- Graceful shutdown — всегда завершай пул потоков корректно
- Обработка InterruptedException — не игнорируй это исключение