forkjoinpool 专用于可递归拆分的 cpu 密集型任务,如归并排序、树遍历、并行 reduce;不适用于 i/o 多、不可分或耗时差异大的场景。
什么时候该用 ForkJoinPool 而不是普通线程池
ForkJoinPool 不是通用线程池替代品,它专为「可递归拆分的 CPU 密集型任务」设计。如果你的任务是 I/O 等待多、无法自然切分(比如单次 HTTP 请求)、或每次子任务耗时差异极大,用 ForkJoinPool 反而降低性能,甚至引发栈溢出或工作窃取失效。
典型适用场景包括:归并排序、树形结构遍历(如 JSON 解析深度优先计算)、大规模数组并行 reduce、分治型数值计算(如矩阵乘法分块)。
- 任务必须能明确 split 成两个或多个子任务,且子任务可独立执行
- 各子任务计算量尽量均衡;严重不均时,
work-stealing效果打折扣 - 避免在
compute()中做阻塞操作(如Thread.sleep()、数据库查询),否则会卡住整个池的工作线程
ForkJoinTask 的两种写法:继承 RecursiveAction 还是 RecursiveTask
区别只在是否需要返回值:RecursiveAction 无返回值(void),适合“执行即完成”类任务(如遍历并修改数组);RecursiveTask<t></t> 必须重写 compute() 并返回 T,适合需要聚合结果的场景(如求和、找最大值)。
不要手动 new 线程或调用 fork()/join() 后再阻塞等待——这是反模式。正确流程是:构造任务 → 提交到 ForkJoinPool → 调用 invoke() 或 submit().get()。
立即学习“Java免费学习笔记(深入)”;