Ответ
FixedThreadPool — это реализация пула потоков (ExecutorService) с фиксированным количеством рабочих потоков. Создаётся с помощью фабричного метода Executors.newFixedThreadPool(int nThreads).
Принцип работы:
- Пул создаёт указанное количество потоков (
nThreads) при инициализации. - Для хранения задач, которые не могут быть выполнены сразу (все потоки заняты), используется неограниченная очередь
LinkedBlockingQueue. - Если поток завершается из-за непойманного исключения, пул создаёт новый поток для поддержания заданного количества.
Пример создания и использования:
import java.util.concurrent.*;
public class FixedThreadPoolExample {
public static void main(String[] args) {
// Создаём пул из 4 потоков
ExecutorService executor = Executors.newFixedThreadPool(4);
// Отправляем 10 задач на выполнение
for (int i = 0; i < 10; i++) {
final int taskId = i;
executor.submit(() -> {
System.out.println("Выполняется задача " + taskId +
" в потоке " + Thread.currentThread().getName());
// Имитация работы
try { Thread.sleep(1000); } catch (InterruptedException e) {}
});
}
// Инициируем упорядоченное завершение: выполняем все отправленные задачи, но не принимаем новые
executor.shutdown();
try {
// Ожидаем завершения всех задач, но не более 1 минуты
if (!executor.awaitTermination(1, TimeUnit.MINUTES)) {
executor.shutdownNow(); // Принудительное завершение
}
} catch (InterruptedException e) {
executor.shutdownNow();
}
}
}
Когда использовать FixedThreadPool:
- CPU-bound задачи: Когда задачи в основном вычислительные (не ждут I/O). Оптимальное количество потоков обычно равно количеству доступных ядер процессора (
Runtime.getRuntime().availableProcessors()). - Когда нужно ограничить параллелизм: Чтобы не перегрузить систему или внешний ресурс (например, базу данных) большим количеством одновременных запросов.
Потенциальные проблемы:
- Утечка памяти (OOM): Поскольку очередь неограничена, при быстром поступлении задач и медленном их выполнении очередь может бесконечно расти, потребляя всю память.
- Взаимоблокировка (Deadlock): Если все потоки ожидают результаты задач, которые находятся в очереди, но не могут начать выполнение из-за отсутствия свободных потоков.
- Простой потоков при I/O: Если задачи связаны с ожиданием I/O (сеть, диск), потоки будут простаивать, что неэффективно. В таких случаях лучше использовать
CachedThreadPoolилиWorkStealingPool.