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

一、概述

forkjion里面的两个重要的概念

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

二、代码实现

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

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

    public static class MyTask extends RecursiveTask<Integer>{

        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<src.length;i++){
                sum = sum + src[i];
            }
            System.out.println("普通遍历结果是: "+sum
                    +"  耗时:"+(System.currentTimeMillis()-start)+"毫秒");
        }

        //创建随机数数组
        public static int[] makeArray() {
            //new一个随机数发生器
            Random r = new Random();
            int[] result = new int[ARRAY_LENGTH];
            for(int i=0;i<ARRAY_LENGTH;i++){
                //用随机数填充数组
                result[i] =  r.nextInt(ARRAY_LENGTH*3);
            }
            return result;

        }

    }

}

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

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

Process finished with exit code 0