ForkJoinPool сам по себе является наследником ExecutorService. Вопрос подразумевает его отличия от обычного пула потоков – ThreadPoolExecutor.

Основное отличие – стратегия work stealing, которая уже упоминалась в предыдущем посте. Этой стратегии посвящена глава 5.3.3 Java Concurrency in Practice.

Преимущества, которые дает work stealing по сравнению с обычным пулом:
• Сокращение расходов на переключение контекста;
• Защита от проблемы голодания потоков (thread starvation);
• Защита от дедлока для рекурсивных задач.

Как положено любому представителю ExecutorService, ForkJoinPool тоже умеет выполнять Runnable и Callable, но помимо этого работает и со специальными задачами ForkJoinTask, о которых также говорилось ранее.

Интерфейс настройки и мониторинга остается тем же, что и в классических тред-пулах.

Каждый обычный пул использует собственный набор потоков. ForkJoinPool по умолчанию использует общий пул-синглтон commonPool. Альтернативный отдельный пул всё еще можно задать в конструкторе.

ForkJoinPool сам регулирует количество запущенных потоков, достигая максимальной эффективности при заданном уровне параллелизма.