Ответ
ForkJoinPool — это специализированная реализация ExecutorService, оптимизированная для эффективного выполнения рекурсивных задач, которые можно разбивать на более мелкие подзадачи (алгоритмы «разделяй и властвуй»).
Ключевые особенности:
- Work-Stealing алгоритм: Каждый рабочий поток имеет свою двустороннюю очередь (deque). Когда поток завершает свои задачи, он может «украсть» задачу из хвоста очереди другого занятого потока. Это эффективно балансирует нагрузку.
- Рекурсивное разбиение: Задачи обычно наследуются от
RecursiveTask<V>(возвращает результат) илиRecursiveAction(не возвращает). - Пул по умолчанию:
ForkJoinPool.commonPool()используется многими параллельными операциями в Java (например,parallelStream()).
Пример: вычисление числа Фибоначчи (для демонстрации, неэффективно на практике):
import java.util.concurrent.*;
class FibonacciTask extends RecursiveTask<Integer> {
final int n;
FibonacciTask(int n) { this.n = n; }
@Override
protected Integer compute() {
if (n <= 1) return n;
FibonacciTask f1 = new FibonacciTask(n - 1);
f1.fork(); // Асинхронный запуск подзадачи в другом потоке
FibonacciTask f2 = new FibonacciTask(n - 2);
return f2.compute() + f1.join(); // Дожидаемся результата f1 и объединяем
}
}
public class Main {
public static void main(String[] args) {
ForkJoinPool pool = new ForkJoinPool();
int result = pool.invoke(new FibonacciTask(10));
System.out.println(result); // 55
}
}
Когда использовать:
- CPU-bound задачи с естественным рекурсивным разбиением (сортировка, обход деревьев, параллельные вычисления).
- Не подходит для задач, связанных с блокирующим I/O, так как потоки будут простаивать.