Какими способами можно создать ExecutorService в Java?

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

Ответ

ExecutorService в Java создается преимущественно через фабричные методы класса java.util.concurrent.Executors или путем прямой настройки ThreadPoolExecutor.

1. Создание с помощью Executors (наиболее распространено)

  • Фиксированный пул потоков (newFixedThreadPool) Создает пул с заданным фиксированным количеством потоков.

    ExecutorService executor = Executors.newFixedThreadPool(4);

    Подходит для задач с предсказуемой нагрузкой.

  • Кэширующий пул потоков (newCachedThreadPool) Создает пул, который создает новые потоки по мере необходимости, но переиспользует незанятые.

    ExecutorService executor = Executors.newCachedThreadPool();

    Подходит для множества коротких асинхронных задач. Может создавать много потоков при пиковой нагрузке.

  • Пул из одного потока (newSingleThreadExecutor) Гарантирует последовательное выполнение задач.

    ExecutorService executor = Executors.newSingleThreadExecutor();

    Подходит для задач, требующих строгого порядка или доступа к общему ресурсу без блокировок.

  • Пул с планировщиком (newScheduledThreadPool) Создает пул для выполнения отложенных или периодических задач.

    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(2);
    scheduler.schedule(() -> System.out.println("Task"), 5, TimeUnit.SECONDS);

2. Прямое создание через ThreadPoolExecutor (для тонкой настройки)

Дает полный контроль над параметрами пула.

ExecutorService customExecutor = new ThreadPoolExecutor(
    2,                      // corePoolSize: минимальное количество рабочих потоков
    10,                     // maximumPoolSize: максимальное количество потоков
    60L, TimeUnit.SECONDS,  // keepAliveTime: время простоя лишних потоков
    new LinkedBlockingQueue<>(100), // workQueue: очередь задач
    Executors.defaultThreadFactory(), // threadFactory: фабрика создания потоков
    new ThreadPoolExecutor.CallerRunsPolicy() // handler: политика при отказе
);

Важно: Завершение работы пула

После использования ExecutorService должен быть корректно остановлен.

executor.shutdown(); // Плавное завершение после выполнения всех задач
executor.shutdownNow(); // Попытка немедленной остановки всех задач
executor.awaitTermination(10, TimeUnit.SECONDS); // Ожидание завершения