Ответ
В Java стандартная библиотека предоставляет несколько реализаций ExecutorService через фабричные методы класса Executors. Каждая предназначена для определённых сценариев.
Основные реализации:
-
FixedThreadPool— пул с фиксированным количеством потоков.- Когда использовать: Когда известно стабильное количество параллельных задач.
ExecutorService executor = Executors.newFixedThreadPool(4);
- Когда использовать: Когда известно стабильное количество параллельных задач.
-
CachedThreadPool— создаёт новые потоки по мере необходимости, переиспользует свободные в течение 60 секунд.- Когда использовать: Для коротких асинхронных задач с переменной нагрузкой. Риск: при высокой нагрузке может создать слишком много потоков.
ExecutorService executor = Executors.newCachedThreadPool();
- Когда использовать: Для коротких асинхронных задач с переменной нагрузкой. Риск: при высокой нагрузке может создать слишком много потоков.
-
SingleThreadExecutor— пул из одного рабочего потока.- Когда использовать: Для последовательного выполнения задач или когда требуется гарантия отсутствия параллелизма.
ExecutorService executor = Executors.newSingleThreadExecutor();
- Когда использовать: Для последовательного выполнения задач или когда требуется гарантия отсутствия параллелизма.
-
ScheduledThreadPool— пул для отложенного или периодического выполнения задач.- Когда использовать: Для планировщиков задач (таймеры, периодические операции).
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2); executor.schedule(task, 5, TimeUnit.SECONDS); // Запустить через 5 секунд executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.MINUTES); // Запускать каждую минуту
- Когда использовать: Для планировщиков задач (таймеры, периодические операции).
-
WorkStealingPool(Java 8+) — основан наForkJoinPool. Использует work-stealing алгоритм.- Когда использовать: Для задач, порождающих множество подзадач (рекурсивные, вычислительно интенсивные), или в приложениях с высокой степенью параллелизма.
ExecutorService executor = Executors.newWorkStealingPool();
- Когда использовать: Для задач, порождающих множество подзадач (рекурсивные, вычислительно интенсивные), или в приложениях с высокой степенью параллелизма.
Важно: Для production-систем часто рекомендуется создавать пулы вручную через ThreadPoolExecutor, чтобы явно контролировать все параметры (размер ядра, максимальный размер, очередь, политику отказа).