ForkJoinPool сам по себе является наследником
ExecutorService. Вопрос подразумевает его отличия от обычного пула потоков –
ThreadPoolExecutor.
Основное отличие – стратегия work stealing, которая уже упоминалась
в предыдущем посте. Этой стратегии посвящена
глава 5.3.3 Java Concurrency in Practice.
Преимущества, которые дает work stealing по сравнению с обычным пулом:
• Сокращение расходов на переключение контекста;
• Защита от проблемы голодания потоков (thread starvation);
• Защита от дедлока для рекурсивных задач.
Как положено любому представителю
ExecutorService,
ForkJoinPool тоже умеет выполнять
Runnable и
Callable, но помимо этого работает и со специальными задачами
ForkJoinTask, о которых также говорилось ранее.
Интерфейс настройки и мониторинга остается тем же, что и в классических тред-пулах.
Каждый обычный пул использует собственный набор потоков.
ForkJoinPool по умолчанию использует общий пул-синглтон
commonPool. Альтернативный отдельный пул всё еще можно задать в конструкторе.
ForkJoinPool сам регулирует количество запущенных потоков, достигая максимальной эффективности при заданном уровне параллелизма.