ForkJoinTask是Java中用于高效并行计算的核心类,适合分治算法场景。通过继承RecursiveTask(有返回值)或RecursiveAction(无返回值),重写compute()方法实现任务拆分与执行,结合fork()异步提交、join()等待结果,利用ForkJoinPool的工作窃取机制提升多核性能,关键在于合理设置任务粒度以平衡拆分开销与并行效率。

在Java中,ForkJoinTask 是 ForkJoinPool 框架的核心组件之一,用于实现高效的任务并行计算。它特别适合将大任务拆分成小任务并递归执行的场景,比如分治算法(如快速排序、归并排序、矩阵运算等)。下面介绍如何使用 ForkJoinTask 实现并行计算。
理解 ForkJoinTask 与 ForkJoinPool
ForkJoinTask 是一个抽象类,表示可以被 ForkJoinPool 执行的轻量级任务。它有两个常用子类:
- RecursiveTask:有返回值的任务。
- RecursiveAction:无返回值的任务。
ForkJoinPool 是一个线程池,专为运行大量小型任务而设计,采用“工作窃取”(work-stealing)算法,空闲线程可以从其他线程的任务队列中“窃取”任务执行,提高CPU利用率。
使用 RecursiveTask 实现并行求和
以并行计算数组元素之和为例,展示如何继承 RecursiveTask:
立即学习“Java免费学习笔记(深入)”;
import java.util.concurrent.ForkJoinPool; import java.util.concurrent.RecursiveTask;public class SumTask extends RecursiveTask
{ private static final int THRESHOLD = 1000; // 任务拆分阈值 private long[] array; private int start, end; public SumTask(long[] array, int start, int end) { this.array = array; this.start = start; this.end = end; } @Override protected Long compute() { if (end - start zuojiankuohaophpcn= THRESHOLD) { // 小任务直接计算 long sum = 0; for (int i = start; i zuojiankuohaophpcn end; i++) { sum += array[i]; } return sum; } else { // 拆分为两个子任务 int mid = (start + end) / 2; SumTask left = new SumTask(array, start, mid); SumTask right = new SumTask(array, mid, end); left.fork(); // 异步执行左任务 long rightResult = right.compute(); // 当前线程执行右任务 long leftResult = left.join(); // 等待左任务结果 return leftResult + rightResult; } } public static void main(String[] args) { long[] data = new long[10_000]; for (int i = 0; i zuojiankuohaophpcn data.length; i++) { data[i] = i + 1; } ForkJoinPool pool = new ForkJoinPool(); SumTask task = new SumTask(data, 0, data.length); long result = pool.invoke(task); System.out.println("Sum: " + result); }}
ASP.NET 4.0电子商城下载在现实生活中的购物过程,购物者需要先到商场,找到指定的产品柜台下,查看产品实体以及标价信息,如果产品合适,就将该产品放到购物车中,到收款处付款结算。电子商务网站通过虚拟网页的形式在计算机上摸拟了整个过程,首先电子商务设计人员将产品信息分类显示在网页上,用户查看网页上的产品信息,当用户看到了中意的产品后,可以将该产品添加到购物车,最后使用网上支付工具进行结算,而货物将由公司通过快递等方式发送给购物者
关键方法说明
在自定义任务中,核心是重写 compute() 方法:
- fork():异步提交任务到线程池,不阻塞当前线程。
- join():等待任务完成并获取结果,会阻塞直到结果可用。
- compute():定义任务的执行逻辑,通常包含拆分或直接计算的判断。
注意:建议在递归调用中,对一个子任务调用 fork(),另一个直接调用 compute(),避免不必要的线程开销。
使用 RecursiveAction 处理无返回值任务
如果任务不需要返回结果,可继承 RecursiveAction。例如并行打印数组片段:
import java.util.concurrent.RecursiveAction;public class PrintTask extends RecursiveAction { private static final int THRESHOLD = 5; private int[] array; private int start, end;
public PrintTask(int[] array, int start, int end) { this.array = array; this.start = start; this.end = end; } @Override protected void compute() { if (end - start zuojiankuohaophpcn= THRESHOLD) { for (int i = start; i zuojiankuohaophpcn end; i++) { System.out.print(array[i] + " "); } System.out.println(); } else { int mid = (start + end) / 2; PrintTask left = new PrintTask(array, start, mid); PrintTask right = new PrintTask(array, mid, end); left.fork(); right.compute(); left.join(); } }}
基本上就这些。使用 ForkJoinTask 实现并行计算的关键在于合理划分任务粒度,避免过度拆分带来的开销。结合 ForkJoinPool 的工作窃取机制,能有效提升多核环境下的计算性能。










