ForkJoinPool核心是分治思想与工作窃取算法:任务通过fork拆分、join合并,每个线程独享双端队列,本地LIFO执行、窃取时FIFO取尾,实现无锁高效负载均衡。

ForkJoinPool 是 Java 并行计算的核心工具之一,专为“分治(Divide-and-Conquer)”类任务设计,底层基于工作窃取(Work-Stealing)算法实现高吞吐、低竞争的并行执行。它不是普通线程池的简单升级,而是从任务调度模型到线程协作机制都做了深度优化。
核心思想:分治 + 工作窃取
任务被不断 fork() 拆分成更小的子任务,直到足够小(如达到阈值)后直接 compute();所有子任务结果通过 join() 合并。关键在于:每个线程维护自己的双端队列(Deque),push/pop 本地任务走栈顶(LIFO),窃取别人任务则从队列尾部(FIFO)拿——这既利于缓存局部性,又避免线程间竞争。
怎么用:继承 RecursiveTask 或 RecursiveAction
实际编码只需两步:
- 定义任务类,继承 RecursiveTask<T>(有返回值)或 RecursiveAction(无返回值)
- 重写 compute() 方法:判断是否需拆分(如数组长度 > 阈值),是则 fork 两个子任务,再 join 合并;否则直接计算
示例(计算数组和):
立即学习“Java免费学习笔记(深入)”;
class SumTask extends RecursiveTask<Long> {
final int[] arr; final int lo, hi; final int THRESHOLD = 1000;
SumTask(int[] arr, int lo, int hi) { this.arr = arr; this.lo = lo; this.hi = hi; }
public Long compute() {
if (hi - lo <= THRESHOLD) {
long sum = 0;
for (int i = lo; i < hi; i++) sum += arr[i];
return sum;
}
int mid = (lo + hi) / 2;
SumTask left = new SumTask(arr, lo, mid);
SumTask right = new SumTask(arr, mid, hi);
left.fork(); // 异步提交左子任务
return right.compute() + left.join(); // 右子任务直接算,再等左结果
}
}线程池创建与配置要点
默认使用 ForkJoinPool.commonPool()(并行度 = CPU 核数 − 1),适合轻量级任务;对 I/O 或阻塞操作,应创建专用实例:
- 显式构造:
new ForkJoinPool(parallelism),parallelism 通常设为 Runtime.getRuntime().availableProcessors() - 避免在 compute() 中调用 blocking IO、synchronized 块、Thread.sleep() —— 会阻塞工作线程,拖慢整个池
- 可设置 asyncMode = true(构造时传入),启用 FIFO 调度,更适合事件驱动或流式任务
为什么比普通线程池更适合分治任务?
普通线程池(如 ThreadPoolExecutor)用共享阻塞队列,任务提交/获取存在锁竞争;而 ForkJoinPool 每个线程有独立队列 + 窃取机制:
- 本地任务无锁执行,快
- 空闲线程自动从其他队列“偷”任务,负载均衡天然完成
- fork/join 的嵌套结构被框架跟踪,能精准释放线程资源(比如 join 时若本线程空闲,就帮忙执行其他任务,而非盲目阻塞)


















