Класс ExecutorService в Java
ExecutorService — это ключевой интерфейс в параллельном программировании на Java, он относится кjava.util.concurrentпакет.
ExecutorService предоставляет более продвинутый способ управления потоками, позволяя разработчикам эффективно выполнять асинхронные задачи без ручного создания и управления потоками.
Основные функции ExecutorService включают:
- Управление пулом потоков: Автоматическое управление жизненным циклом потоков, снижающее накладные расходы на создание и уничтожение потоков.
- Планирование задач: Поддерживает отправку
RunnableилиCallableзадач и возвращаетFutureобъекты для отслеживания статуса выполнения задачи. - Оптимизация ресурсов: Повторное использование потоков через пул потоков для повышения производительности системы.
Основные методы ExecutorService
ExecutorService предоставляет несколько методов для отправки, управления и контроля выполнения задач. Вот несколько ключевых методов:
submit()
Используется для отправки задачи (RunnableилиCallable) и возвращаетFutureобъект, чтобы проверить, завершена ли задача, или получить возвращаемое значение.
Пример
Future<?> future = executor.submit(() -> {
System.out.println("Task is running");
});
execute()
Используется только для отправкиRunnableзадач, без возврата каких-либо результатов.
Пример
System.out.println("Task executed");
});
shutdown()
Корректно завершает работу пула потоков, больше не принимает новые задачи, но ожидает завершения уже отправленных задач.
Пример
shutdownNow()
Немедленно завершить работу пула потоков, попытаться прервать все выполняющиеся задачи и вернуть список задач, которые не были выполнены.
Пример
awaitTermination()
Дождаться завершения работы пула потоков, пока все задачи не завершатся или не истечёт тайм-аут.
Пример
Как создать ExecutorService
Java предоставляетExecutorsслужебный класс для создания различных типов пулов потоков:
newFixedThreadPool(int nThreads)
Создаёт пул потоков фиксированного размера, подходящий для задач со стабильной нагрузкой.
Пример
newCachedThreadPool()
Создаёт кэшированный пул потоков, подходящий для короткоживущих асинхронных задач.
Пример
newSingleThreadExecutor()
Создать однопоточный пул потоков, подходящий для последовательно выполняемых задач.
Пример
newScheduledThreadPool(int corePoolSize)
Создать пул потоков, поддерживающий запланированные или периодические задачи.
Пример
Примеры использования
Отправка задач Runnable
Пример
executor.submit(() -> {
System.out.println("Задача 1 выполняется");
});
executor.submit(() -> {
System.out.println("Задача 2 выполняется");
});
executor.shutdown();
Отправка задач Callable и получение результатов
Пример
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();
Лучшие практики
Разумно установите размер пула потоков:
- Задачи с интенсивным использованием CPU:
线程数 = CPU 核心数 + 1 - Задачи с интенсивным вводом-выводом:
线程数 = CPU 核心数 * 2
- Задачи с интенсивным использованием CPU:
Избегайте утечек памяти:
- Обязательно вызовите
shutdown()илиshutdownNow()для завершения работы пула потоков.
- Обязательно вызовите
Обрабатывайте исключения:
- Используйте
try-catchчтобы перехватывать исключения в задачах, предотвращая неожиданное завершение потоков.
- Используйте
Используйте
Futureдля управления задачами:- Через
Future.get()получать результаты задач или проверять статус задач.
- Через