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