java多线程之并行框架ForkJoin

来源:互联网 发布:mysql gbk utf8 区别 编辑:程序博客网 时间:2024/05/29 07:21

在java7中新加入了ForkJoin,我是一个特别容易被新这个字吸引的人,好奇之下就去查了查资料,它是Java7提供的原生多线程并行处理框架,其基本思想是将一个大任务分割为一个个独立执行的子任务,再将子任务得到的结果聚合起来最终的result,在我看来,他的思想和快速排序算法有异曲同工之妙。ok,我们先看看我参照大神写的demo。

public class ForkJoin extends RecursiveTask<Integer> {    public static final int threshold = 2;    private int start;    private int end;    public ForkJoin(int start, int end){        this.start = start;        this.end = end;    }    @Override    protected Integer compute() {        int sum = 0;        boolean bool = (end - start)/2 <= threshold;        if(bool){            for(int i = start; i<= end;i++){                sum += i;            }        } else {            int center = (start+end)/2;            ForkJoin one = new ForkJoin(start,center);            ForkJoin two = new ForkJoin(center+1,end);            one.fork();//执行子任务            two.fork();            int oneResult = one.join();//得到结果            int twoResult = two.join();            sum = oneResult+twoResult;        }        return sum;    }    public static void main(String[] args) throws ExecutionException, InterruptedException {        ForkJoinPool pool = new ForkJoinPool();        ForkJoin forkJoin = new ForkJoin(1,100);        Future<Integer> result = pool.submit(forkJoin);        int i = result.get();        System.out.print(i);    }}
首先可以看到我们继承了RecursiveTask<T>类,我们需要注意的是:我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join的操作机制,通常我们不直接继承ForkjoinTask类,只需要直接继承其子类。 RecursiveAction:用于没有返回结果的任   务; RecursiveTask:用于有返回值的任务。这里我使用的是RecursiveTask<T>,这里的T是我们期望得到的结果的类型。我们还必须实现compute方法,定义我们具体的任务细节。

大家可以看到fork()是执行子任务:

public final ForkJoinTask<V> fork() {    Thread t;    if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)        ((ForkJoinWorkerThread)t).workQueue.push(this);    else        ForkJoinPool.common.externalPush(this);    return this;}
这个是fork方法的源码,在当前任务正在运行的池中异步执行此任务(如果适用),或使用ForkJoinPool.commonPool()如果不是inForkJoinPool())进行异步执行 。这个是java api的解释,很明显是把我们的任务加入到了工作队列中去。fork方法是得到我们任务的结果,然后将结果聚合一下就定义好了我们的任务,就是一个累加。

接下来再来看main方法里面的代码,ForkJoinPool是什么呢?查看源码可以发现public class ForkJoinPoolextendsAbstractExecutorService,是不是立马就感觉原来如此,对的,ForkJoinPool就是专为forkjoin框架定制的线程池,具体的实现细节咱们可以先不看,一看到submit是不是感觉很熟悉,没错我也是这样,看到这个方法我就想起了callable接口,事实上的确如同我们猜测的那样,这两个方法的作用是类似的,都是执行任务并得到返回结果。

得到的结果如图所示:

5050
Process finished with exit code 0

像这种求和以及排序的需求都可以通过FORKJOIN思想来实现,希望对大家有所帮助。

原创粉丝点击