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

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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值