Ответ
ExecutorService решает ключевую проблему «один поток на задачу»: создание 10000 потоков нативно (new Thread()) приведет к огромным накладным расходам на управление памятью и переключение контекста, что может исчерпать ресурсы системы и привести к ее зависанию.
Преимущества ExecutorService с пулом потоков:
- Контроль ресурсов: Пул потоков фиксированного размера (например, 10 потоков) переиспользует существующие потоки для выполнения всех задач, избегая затрат на их создание и уничтожение.
- Очередь задач: Задачи, которые не могут быть немедленно выполнены, помещаются в очередь (
BlockingQueue) и обрабатываются по мере освобождения потоков. - Управление жизненным циклом: Предоставляет методы для плавной остановки (
shutdown(),awaitTermination()) и принудительной отмены выполнения. - Получение результатов: Возвращает объекты
Future<T>, позволяющие получить результат асинхронной задачи или исключение.
Пример обработки 10000 задач:
import java.util.concurrent.*;
public class TaskProcessor {
private static final int TASK_COUNT = 10000;
private static final int POOL_SIZE = 10;
public static void main(String[] args) throws InterruptedException {
// Создаем пул из 10 потоков
ExecutorService executor = Executors.newFixedThreadPool(POOL_SIZE);
for (int i = 0; i < TASK_COUNT; i++) {
int taskId = i;
executor.submit(() -> {
System.out.println("Выполняется задача " + taskId + " в потоке " + Thread.currentThread().getName());
// Логика задачи...
});
}
// Инициируем плавное завершение: выполняем все задачи из очереди, но не принимаем новые.
executor.shutdown();
// Ожидаем завершения всех задач, но не более 1 часа.
executor.awaitTermination(1, TimeUnit.HOURS);
}
}
Такой подход обеспечивает высокую пропускную способность при ограниченном потреблении ресурсов.