Java JUC并发之ForkJoin入门

十四、ForkJoin

什么是fork join

JDK1.7开始

并行执行任务!提高效率 => 针对大数据量

大数据 => MapReduce (把把任务拆分成小任务)

ForkJoin 特点 : 工作窃取

已经执行完任务的线程会将尚未执行完的线程中的任务窃取过来,避免线程等待造成资源浪费 => 提高效率

这里维护的都是双端队列 Deque 【队列两端都可以存取】

ForkJoin测试

package com.liu.forkjoin;

import java.util.concurrent.RecursiveTask;

/**
 * 求和计算的任务
 * 3000=>for   6000 => forkjoin  9000 => Stream并行流
 */
public class ForkJoinDemo extends RecursiveTask<Long> {

    private Long start;
    private Long end;

    private Long temp = 10000L;

    public ForkJoinDemo(Long start,Long end) {
        this.start = start;
        this.end = end;
    }

    public static void main(String[] args) {

        int sum = 0;

        for (int i = 1; i <= 10_0000_0000; i++) {
            sum += i;
        }
        System.out.println(sum);
    }

    @Override
    protected Long compute() {
        if ((end-start) < temp){ // 一般的求和

            Long sum = 0L;
            for (Long i = start; i <= end ; i++) {
                sum += i;

            }
            return sum;

        }else{
            // 分支合并计算
            Long middle = (start + end)/2; // 中间值

            ForkJoinDemo task1 = new ForkJoinDemo(start, middle);
            task1.fork(); // 拆分任务,把任务压入线程
            ForkJoinDemo task2 = new ForkJoinDemo(middle + 1, end);
            task2.fork();

            return task1.join() + task2.join();

        }
    }
}

测试类 Test

package com.liu.forkjoin;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.DoubleStream;
import java.util.stream.IntStream;
import java.util.stream.LongStream;

// 测试类 求 0-10_0000_0000的和
public class Test {

    //同一个任务 效率高几十倍!!
    public static void main(String[] args) throws ExecutionException, InterruptedException {

      //  test1(); // 6303
      //  test2(); // 5846
        test3(); // 150 ???
    }

    // 普通程序员
    public static void test1(){
        Long sum = 0L;
        Long start = System.currentTimeMillis(); // 记录任务开始时间

        for (Long i = 1L; i <= 10_0000_0000; i++) {
            sum += i;
        }

        Long end = System.currentTimeMillis(); // 记录任务完成时间

        System.out.println("sum = " + sum + " 时间 :" + (end -start));
    }


    // ForkJoin
    public static void test2() throws ExecutionException, InterruptedException {

        Long start = System.currentTimeMillis();

        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Long> task = new ForkJoinDemo(0L, 10_0000_0000L);
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);// 提交任务
        Long sum = submit.get();

        Long end = System.currentTimeMillis();
        System.out.println("sum = " + sum + " 时间 :" + (end -start));

    }

    // Stream并行流 调用API
    public static void test3(){

        Long start = System.currentTimeMillis();

        // Stream并行流
        // DoubleStream
        // IntStream.rangeClosed()
        Long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0,Long::sum); // sum是一个求和函数 返回一个a+b的和


        Long end = System.currentTimeMillis();

        System.out.println("sum = " + sum + " 时间 :" + (end -start));

    }
}

本质 :(RecursiveTask) 递归 返回一个ForkJoinTask

posted @ 2021-07-15 17:36  夕立君  阅读(60)  评论(0编辑  收藏  举报