12.Stream Fork和Join原理-与【案例实战】

28 阅读1分钟

12.Stream Fork和Join原理

parallelStream() 使用的是Fork/Join 框架,Fork/Join框架自JDK7引入。

Fork/Join 框架可以将一个大任务拆分为很多小任务来异步执行。

Fork/Join 框架主要包含三个模块:

  1. 线程池:ForkJoinPool
  2. 任务对象:ForkJoinTask
  3. 执行任务的线程:ForkJoinWorkerThread

image.png

image.png

image.png

image.png

案例 Fork/Join案例

需求:

使用 Fork/Join 计算1-10000的和,当一个任务的计算数量大于3000的时候,拆分任务。 数量小于3000的时候就计算。

image.png

@Test
public void test1() {
    long statr = System.currentTimeMillis();
    ForkJoinPool pool = new ForkJoinPool();
    SumRecursiveTask task = new SumRecursiveTask(1, 10000l);
    Long result = pool.invoke(task);
    System.out.println("result = " + result);

    long times = System.currentTimeMillis() - statr;
    System.out.println("times = " + times);
}

class SumRecursiveTask extends RecursiveTask<Long>{

    // 定义一个拆分的临界值
    private static  final long THRESHOLD = 3000l;

    private final long start;

    public SumRecursiveTask(long start, long end) {
        this.start = start;
        this.end = end;
    }

    private final  long end;

    @Override
    protected Long compute() {

        // 写算法
        long length = end - start;

        if (length <=THRESHOLD){
            // 任务不用拆分,可以计算
            long sum = 0;
            for (long i = start; i <= end; i++) {
                sum += i;
            }
            System.out.println("计算 = " + start + "-->" + end +",的结果为:" + sum);
            return sum;
        }else{

            // 数量大于预定的数量,那说明任务还需要继续拆分
            long middle = (start + end) / 2;
            System.out.println("拆分:左边" + start + "-->" + middle + ",右边" + (middle + 1)+"-->"+ end);
            SumRecursiveTask leftTask = new SumRecursiveTask(start, middle);
            SumRecursiveTask rightTask = new SumRecursiveTask(middle + 1, end);

            // fork拆分
            leftTask.fork();
            rightTask.fork();

            // join归并
            return leftTask.join() + rightTask.join();

        }
    }
}
拆分:左边1-->5000,右边5001-->10000
拆分:左边1-->2500,右边2501-->5000
拆分:左边5001-->7500,右边7501-->10000
计算 = 1-->2500,的结果为:3126250
计算 = 5001-->7500,的结果为:15626250
计算 = 2501-->5000,的结果为:9376250
计算 = 7501-->10000,的结果为:21876250
result = 50005000
times = 3