并发编程(6) —— forkjoin

上一篇:并发编程(5)—— 常用方法

一、概述

forkjion里面的两个重要的概念

分而治之,什么是分而治之?
一个大的事情平均分成几个相同小的事情,如果没有达到最小的要求,就继续分,一直分到达到的要求。
工作密取,workStealing
如果分而治之的线程很多,就会形成线程的队列,这里面就会有完成的快和慢的不同线程。快的线程执行完成以后,就会把慢的队列拿过来进行执行。

并发编程(6) —— forkjoin_第1张图片
RecursiveAction:无返回值的任务,通常用于只fork不join的情形。
RecursiveTask:有返回值的任务,通常用于fork+join的情形。

二、代码实现

RecursiveTask有返回值的任务

//计算长度为ARRAY_LENGTH  数组中的数值总和
public class TestForkJoin {

    //数组长度
    public static final int ARRAY_LENGTH  = 100000000;

    public static class MyTask extends RecursiveTask{

        private final static int THRESHOLD = MakeArray.ARRAY_LENGTH/10;
        private int[] src; //表示我们要实际统计的数组
        private int fromIndex;//开始统计的下标
        private int toIndex;//统计到哪里结束的下标

        MyTask(int[] src, int fromIndex, int toIndex){
            this.src = src;
            this.fromIndex = fromIndex;
            this.toIndex = toIndex;
        }

        @Override
        protected Integer compute() {
            if(toIndex - fromIndex < THRESHOLD){
                int count = 0;
                for (int i = fromIndex; i <= toIndex ; i++) {
                    count = count + src[i];
                }
                return count;
            }else{
                int mid = (fromIndex + toIndex) / 2;
                MyTask left = new MyTask(src,fromIndex,mid);
                MyTask right = new MyTask(src,mid+1,toIndex);
                invokeAll(left,right);
                return left.join()+right.join();
            }
        }


        public static void main(String[] args) {
        	//使用forkJoin
            ForkJoinPool forkJoinPool = new ForkJoinPool();
            int[] src = makeArray();
            MyTask myTask = new MyTask(src,0,src.length-1);
            long currentTimeMillis = System.currentTimeMillis();
            Integer invoke = forkJoinPool.invoke(myTask);//同步调用
            System.out.println("forkjoin结果是: "+invoke+"  耗时:"+(System.currentTimeMillis() - currentTimeMillis)+"毫秒");


			//使用普通遍历求和
            long start = System.currentTimeMillis();
            int sum= 0;
            for(int i= 0;i

运行结果:当数组长度比较大的时候,使用forkjoin总是比普通遍历求和要快

forkjoin结果是: -872683364  耗时:45毫秒
普通便利结果是: -872683364  耗时:58毫秒

Process finished with exit code 0

RecursiveAction无返回值的任务

public class ForkJoinTest extends RecursiveAction {

    private File file;

    public ForkJoinTest(File file){
        this.file = file;
    }

    public static void main(String[] args){
        ForkJoinPool pool =new ForkJoinPool();
        ForkJoinTest task = new ForkJoinTest(new File("D:\\wanglin\\wangl"));
        pool.execute(task);//异步调用加入任务
        System.out.println("Task is start");
        task.join();//阻塞(因为主线程运行完forkjoin还未运行完成就会被终止)
        System.out.println("Tash is end");
    }

    @Override
    protected void compute() {
        List subTasks = new ArrayList<>();
        File[] files = file.listFiles();
        for(File file:files){
            if(file.isDirectory()){
                subTasks.add(new ForkJoinTest(file));
            }else {
                System.out.println(file.getAbsolutePath());
            }
        }
        if(!subTasks.isEmpty()){
            for(ForkJoinTest task:invokeAll(subTasks)){
                task.join();
            }
        }
    }
}

你可能感兴趣的:(并发,并发编程)