java并发包:fork/join

来源:互联网 发布:qq会员签到软件 编辑:程序博客网 时间:2024/06/07 00:20

本文转载至:http://blog.csdn.net/a910626/article/details/51900967

Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

  我们再通过Fork和Join这两个单词来理解下Fork/Join框架,Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算1+2+。。+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务的结果。Fork/Join的运行流程图如下:

  我们已经很清楚Fork/Join框架的需求了,那么我们可以思考一下,如果让我们来设计一个Fork/Join框架,该如何设计?这个思考有助于你理解Fork/Join框架的设计。

  第一步分割任务。首先我们需要有一个fork类来把大任务分割成子任务,有可能子任务还是很大,所以还需要不停的分割,直到分割出的子任务足够小。

  第二步执行任务并合并结果。分割的子任务分别放在双端队列里,然后几个启动线程分别从双端队列里获取任务执行。子任务执行完的结果都统一放在一个队列里,启动一个线程从队列里拿数据,然后合并这些数据。

Fork/Join使用两个类来完成以上两件事情:

ForkJoinTask:我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制,通常情况下我们不需要直接继承ForkJoinTask类,而只需要继承它的子类,Fork/Join框架提供了以下两个子类: 
RecursiveAction:用于没有返回结果的任务。 
RecursiveTask :用于有返回结果的任务。 
ForkJoinPool :ForkJoinTask需要通过ForkJoinPool来执行,任务分割出的子任务会添加到当前工作线程所维护的双端队列中,进入队列的头部。当一个工作线程的队列里暂时没有任务时,它会随机从其他工作线程的队列的尾部获取一个任务。

例子

/** * Created by niehongtao on 16/7/12. * join/fork结构 */public class CountTask extends RecursiveTask<Long> {    private static final int THRESHOLD = 10000;    private long start;    private long end;    public CountTask(long start, long end) {        this.start = start;        this.end = end;    }    @Override    protected Long compute() {        long sum = 0;        boolean canCompute = (end - start) < THRESHOLD;        if (canCompute) {            for (long i = 0; i <= end; i++) {                sum += i;            }        } else {            // 分成100个小任务            long step = (start + end)/100;            ArrayList<CountTask> countTasks = new ArrayList<>();            long pos = start;            for (int i = 0; i < 100; i++) {                long lastOne = pos + step;                if (lastOne > end) {                    lastOne = end;                }                CountTask countTask = new CountTask(pos, lastOne);                pos += step + 1;                countTasks.add(countTask);                countTask.fork();            }            for (CountTask task : countTasks) {                sum += task.join();            }        }        return sum;    }    public static void main(String[] args) {        ForkJoinPool forkJoinPool = new ForkJoinPool();        CountTask task = new CountTask(0, 200000L);        ForkJoinTask<Long> result = forkJoinPool.submit(task);        try {            long res = result.get();            System.out.print("sum=" + res);        } catch (InterruptedException e) {            e.printStackTrace();        } catch (ExecutionException e) {            e.printStackTrace();        }    }}


0 0
原创粉丝点击