1.Fork/Join框架简介
Fork/Join 它可以将一个大的任务拆分成多个子任务进行并行处理,最后将子任务结果合并成最后的计算结果,并进行输出。Fork/Join 框架要完成两件事情:
Fork:把一个复杂任务进行分拆,大事化小 :把一个复杂任务进行分拆,大事化小
Join:把分拆任务的结果进行合并
在 Java 的 Fork/Join 框架中,使用两个类完成上述操作:
ForkJoinTask: 我们要使用 Fork/Join 框架,首先需要创建一个 ForkJoin 任务。该类提供了在任务中执行 fork 和 join 的机制。通常情况下我们不需要直接集成 ForkJoinTask 类,只需要继承它的子类,Fork/Join 框架提供了两个子类:
- RecursiveAction:用于没有返回结果的任务
- RecursiveTask:用于有返回结果的任务
ForkJoinPool: ForkJoinTask 需要通过 ForkJoinPool 来执行。
RecursiveTask: 继承后可以实现递归(自己调自己)调用的任务。
可以在jdk官方文档中看到:
2.简单应用
实现从 1 + 2 + ... + 100 ,将它们拆分成多个小任务,分别求和,最终再将这些结果合并。
这里就是参照官方文档,先继承RecursiveTask类,重写其中的compute方法,然后定义有参构造,而ForkJoinTask需要通过 ForkJoinPool 来执行,所以还需要创建 分支合并池ForkJoinPool对象。
package test.forkjoin; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; import java.util.concurrent.RecursiveTask; /** * */ class MyTask extends RecursiveTask<Integer> { //拆分差值不能超过10,每次计算10以内的连加操作 private static final Integer NUMBER = 10; private int begin; //拆分左区间的值 private int end; //拆分右区间的值 private int result; //最终结果 public MyTask(int begin,int end) { this.begin = begin; this.end = end; } @Override protected Integer compute() { //判断区间差值是否大于10 if ((end - begin) <= NUMBER) { //将区间内的值依次相加 for (int i = begin; i <= end; i++) { result += i; } } else { //区间差值大于10,进一步拆分 //获取中间值 int middle = (begin + end) / 2; //拆分的左区间 MyTask taskLeft = new MyTask(begin,middle); //拆分的右区间 MyTask taskRight = new MyTask(middle + 1,end); //fork方法进行拆分 taskLeft.fork(); taskRight.fork(); //join方法进行合并 result = taskLeft.join() + taskRight.join(); } return result; } } public class ForkJoinDemo { public static void main(String[] args) { //创建MyTask对象 MyTask myTask = new MyTask(1,100); //创建分支合并池对象 ForkJoinPool forkJoinPool = new ForkJoinPool(); ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(myTask); try { //获取最终合并后的结果 Integer ans = forkJoinTask.get(); System.out.println(ans); } catch (Exception e) { e.printStackTrace(); }finally { //关闭池对象 forkJoinPool.shutdown(); } } }