ForkJoin并发框架—样例及实现分析

来源:互联网 发布:知合控股 封锐 编辑:程序博客网 时间:2024/06/03 17:42

1. JDK中ForkJoin实现概述

在JavaSE7的API和JDK1.7中,分别集成了支持ForkJoin的五个类:

  • ForkJoinPool 实现ForkJoin的线程池
  • ForkJoinWorkerThread 实现ForkJoin的线程
  • ForkJoinTask 一个描述ForkJoin的抽象类
  • RecursiveAction 无返回结果的ForkJoinTask实现
  • RecursiveTask 有返回结果的ForkJoinTask实现

ForkJoin样例解析

public class ForkJoinAction {    public static void main(String[] args) {        //创建一个包含20个并行线程的ForkJoinPool        ForkJoinPool pool = new ForkJoinPool(20);        //创建一个包含三个子任务的forkjointask        List<ChildTask> childTaskList = new ArrayList<ChildTask>();        childTaskList.add(new ChildTask());        childTaskList.add(new ChildTask());        childTaskList.add(new ChildTask());        ParentTask task = new ParentTask(childTaskList, 0, childTaskList.size());        /*把任务放入到  1、当前线程队列(当当前线程为ForkJoinWorkerThread时)或者  2、线程池队列中         * 1、会被当前线程执行或者被别的ForkJoinWorkerThread窃取执行         * 2、线程池队列中的任务最后被执行,执行顺序1、线程任务队列中的task,2、窃取别的线程的task,3、执行线程池中的task。         * */        pool.execute(task);        while(!task.isDone()&&(!task.isCancelled())){            try {                Thread.sleep(1000);            } catch (InterruptedException e) {                e.printStackTrace();            }        }        int result = task.getRawResult();        System.out.println(result);    }}
public class ParentTask extends RecursiveTask<Integer>{    private int TaskGgranularity;//最小任务粒度    List<ChildTask> childTaskList;    private int start;    private int end;    public ParentTask(List<ChildTask> childTaskList, int start, int end){        this.childTaskList = childTaskList;        this.start = start;        this.end = end;    }    /**     * ForkJoinWorkerThread执行执行task的入口,并且返回值会被赋值给result,由getRawResult()取出     */    @Override    protected Integer compute() {        if(childTaskList==null||childTaskList.size()==0) return 0;        if(end-start<=TaskGgranularity){//如果子任务粒度已经达到最小任务粒度,即任务不需再拆分。当前ForkJoinWorkerThread自己自行            ChildTask task = childTaskList.get(start);            return task.compute();        }else{//如果子任务粒度没有达到最小任务粒度,则把任务从中间一分为二            int middle = (start + end) /2;            ParentTask task1 = new ParentTask(childTaskList, start, middle);            ParentTask task2 = new ParentTask(childTaskList, middle, end);            /*当前ForkJoinWorkerThread执行task1,并把task2放入到线程任务队列当中,通常task2会被别的任务线程窃取执行(并发,fork的体现)             * 并且只有当两个task都已经被执行完成时,才会继续往后面走(join的体现)             */                     invokeAll(task1, task2);            //返回task1+task2的执行结果(compute()的返回值)            return task1.getRawResult()+task2.getRawResult();        }    }}
public class ChildTask extends RecursiveTask<Integer>{    @Override    protected Integer compute() {        return calc();    }    private int calc() {        return 10;    }}
public static void invokeAll(ForkJoinTask<?> t1, ForkJoinTask<?> t2) {        t2.fork();//放入到线程task队列中,被别的线程窃取执行        t1.invoke();//当前线程执行        t2.join();//等待被窃取的线程执行完t2任务后,合并    }

以上代码部分已经注释的很明白,详细原理可以自己去看源代码。

0 0