Какие встроенные реализации ExecutorService существуют в Java?

«Какие встроенные реализации ExecutorService существуют в Java?» — вопрос из категории Java Core, который задают на 24% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Java стандартная библиотека предоставляет несколько реализаций ExecutorService через фабричные методы класса Executors. Каждая предназначена для определённых сценариев.

Основные реализации:

  1. FixedThreadPool — пул с фиксированным количеством потоков.

    • Когда использовать: Когда известно стабильное количество параллельных задач.
      ExecutorService executor = Executors.newFixedThreadPool(4);
  2. CachedThreadPool — создаёт новые потоки по мере необходимости, переиспользует свободные в течение 60 секунд.

    • Когда использовать: Для коротких асинхронных задач с переменной нагрузкой. Риск: при высокой нагрузке может создать слишком много потоков.
      ExecutorService executor = Executors.newCachedThreadPool();
  3. SingleThreadExecutor — пул из одного рабочего потока.

    • Когда использовать: Для последовательного выполнения задач или когда требуется гарантия отсутствия параллелизма.
      ExecutorService executor = Executors.newSingleThreadExecutor();
  4. ScheduledThreadPool — пул для отложенного или периодического выполнения задач.

    • Когда использовать: Для планировщиков задач (таймеры, периодические операции).
      ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
      executor.schedule(task, 5, TimeUnit.SECONDS); // Запустить через 5 секунд
      executor.scheduleAtFixedRate(task, 0, 1, TimeUnit.MINUTES); // Запускать каждую минуту
  5. WorkStealingPool (Java 8+) — основан на ForkJoinPool. Использует work-stealing алгоритм.

    • Когда использовать: Для задач, порождающих множество подзадач (рекурсивные, вычислительно интенсивные), или в приложениях с высокой степенью параллелизма.
      ExecutorService executor = Executors.newWorkStealingPool();

Важно: Для production-систем часто рекомендуется создавать пулы вручную через ThreadPoolExecutor, чтобы явно контролировать все параметры (размер ядра, максимальный размер, очередь, политику отказа).