Что такое Fork/Join framework и work stealing?
Fork/Join — рекурсивное деление задачи на подзадачи (fork) с последующим объединением результатов (join). Work stealing: у каждого рабочего потока своя двусторонняя очередь, а освободившийся поток крадёт задачи с хвоста чужой очереди — нагрузка балансируется сама.
- RecursiveTask возвращает результат, RecursiveAction — нет
- Для CPU-bound задач без блокировок
- На нём работают parallel stream и async-методы CompletableFuture (commonPool)
А ещё Порог деления: слишком мелкие задачи съедают выигрыш накладными расходами
Подробно
Модель. Задача проверяет размер: мала — решает напрямую, иначе делится на части, одну отправляет fork(), другую решает сама, затем join() собирает результат.
class Sum extends RecursiveTask<Long> {
protected Long compute() {
if (hi - lo < 10_000) return directSum();
Sum left = new Sum(arr, lo, mid);
left.fork();
long right = new Sum(arr, mid, hi).compute();
return left.join() + right;
}
}
Work stealing. Каждый поток ForkJoinPool кладёт свои подзадачи в собственную деку и берёт их с головы (LIFO — горячие данные в кэше). Свободный поток крадёт у других с хвоста — там самые крупные, ещё не разделённые задачи. Нет единой очереди, за которую бьются все.
Ограничения:
- задачи не должны блокироваться: заблокированный поток не делает работу, а пул фиксированного размера;
- выигрыш только при достаточном объёме и разумном пороге деления;
ForkJoinPool.commonPool()общий на всю JVM — его используют parallel stream и CompletableFuture без своего executor.
Что хотят услышать
- Рекурсивное деление и объединение.
- Механика work stealing и зачем дека.
- Для каких задач подходит и связь с commonPool.
Частые ошибки
- Запускать долгий blocking IO в common ForkJoinPool.
- Делить задачу слишком мелко и тратить время на overhead.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Пул потоков для блокирующих задач ввода-вывода вроде запросов к базе
- ✗Фреймворк, который запускает каждую подзадачу в отдельном новом потоке операционной системы и ждёт их через join
- ✓Рекурсивное деление и кража задач из чужих очередей
- ✗Общая очередь, из которой все потоки берут задачи строго по порядку
Что спросят дальше
- Как parallelStream связан с ForkJoinPool?
- Когда parallelStream вреден?
Разбор темы
- ThreadLocal и Fork/Join
Состояние на поток и утечки в пулах, InheritableThreadLocal, work-stealing в ForkJoinPool и общий пул parallel streams.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.