Класс ExecutorService в Java

ExecutorService — это ключевой интерфейс в параллельном программировании на Java, он относится кjava.util.concurrentпакет.

ExecutorService предоставляет более продвинутый способ управления потоками, позволяя разработчикам эффективно выполнять асинхронные задачи без ручного создания и управления потоками.

Основные функции ExecutorService включают:

  • Управление пулом потоков: Автоматическое управление жизненным циклом потоков, снижающее накладные расходы на создание и уничтожение потоков.
  • Планирование задач: Поддерживает отправкуRunnableилиCallableзадач и возвращаетFutureобъекты для отслеживания статуса выполнения задачи.
  • Оптимизация ресурсов: Повторное использование потоков через пул потоков для повышения производительности системы.

Основные методы ExecutorService

ExecutorService предоставляет несколько методов для отправки, управления и контроля выполнения задач. Вот несколько ключевых методов:

submit()

Используется для отправки задачи (RunnableилиCallable) и возвращаетFutureобъект, чтобы проверить, завершена ли задача, или получить возвращаемое значение.

Пример

ExecutorService executor = Executors.newFixedThreadPool(2);
Future<?> future = executor.submit(() -> {
    System.out.println("Task is running");
});

execute()

Используется только для отправкиRunnableзадач, без возврата каких-либо результатов.

Пример

executor.execute(() -> {
    System.out.println("Task executed");
});

shutdown()

Корректно завершает работу пула потоков, больше не принимает новые задачи, но ожидает завершения уже отправленных задач.

Пример

executor.shutdown();

shutdownNow()

Немедленно завершить работу пула потоков, попытаться прервать все выполняющиеся задачи и вернуть список задач, которые не были выполнены.

Пример

List<Runnable> notExecutedTasks = executor.shutdownNow();

awaitTermination()

Дождаться завершения работы пула потоков, пока все задачи не завершатся или не истечёт тайм-аут.

Пример

executor.awaitTermination(10, TimeUnit.SECONDS);

Как создать ExecutorService

Java предоставляетExecutorsслужебный класс для создания различных типов пулов потоков:

newFixedThreadPool(int nThreads)

Создаёт пул потоков фиксированного размера, подходящий для задач со стабильной нагрузкой.

Пример

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);

newCachedThreadPool()

Создаёт кэшированный пул потоков, подходящий для короткоживущих асинхронных задач.

Пример

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

newSingleThreadExecutor()

Создать однопоточный пул потоков, подходящий для последовательно выполняемых задач.

Пример

ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();

newScheduledThreadPool(int corePoolSize)

Создать пул потоков, поддерживающий запланированные или периодические задачи.

Пример

ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(2);

Примеры использования

Отправка задач Runnable

Пример

ExecutorService executor = Executors.newFixedThreadPool(2);

executor.submit(() -> {
    System.out.println("Задача 1 выполняется");
});

executor.submit(() -> {
    System.out.println("Задача 2 выполняется");
});

executor.shutdown();

Отправка задач Callable и получение результатов

Пример

ExecutorService executor = Executors.newFixedThreadPool(2);

Future<String> future = executor.submit(() -> {
    Thread.sleep(1000);
    return "Задача завершена";
});

try {
    String result = future.get(); // Ожидает завершения задачи
    System.out.println(result);
} catch (Exception e) {
    e.printStackTrace();
}

executor.shutdown();

Лучшие практики

  1. Разумно установите размер пула потоков:

    • Задачи с интенсивным использованием CPU:线程数 = CPU 核心数 + 1
    • Задачи с интенсивным вводом-выводом:线程数 = CPU 核心数 * 2
  2. Избегайте утечек памяти:

    • Обязательно вызовитеshutdown()илиshutdownNow()для завершения работы пула потоков.
  3. Обрабатывайте исключения:

    • Используйтеtry-catchчтобы перехватывать исключения в задачах, предотвращая неожиданное завершение потоков.
  4. ИспользуйтеFutureдля управления задачами:

    • ЧерезFuture.get()получать результаты задач или проверять статус задач.
Другие расширения