ForkJoin

什么是ForkJoin 并行执行任务 提高效率(大数据量时)

大数据:MapReduce 把大任务拆分为小任务

ForkJoin

ForkJoin特点 工作窃取 维护了一个双端队列

当两个线程同时执行时,其中一个线程先执行完,可以偷取未执行完线程的工作帮助它执行

ForkJoin操作

定义一个计算类继承 RecursiveTask

/*求和计算*/
public class ForkJoinTest extends RecursiveTask<Long> {
    private Long start;
    private Long end;
    private Long temp=100000L;

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

    //如果小于临界值,就用普通方式,否则使用forkJoin方式
    @Override
    protected Long compute() {
        if(end-start<temp){
            //分支合并计算 如何使用forkJoin
            /*
             * 1. forkJoinPool
             * 2. 计算任务,forkJoinPool.execute(ForkJoinTask task)
             * 3. 计算类继承 RecursiveTask<Long> 类*/
            Long sum=0L;
            for(Long i=start;i<=end;i++)
            {
                sum=sum+i;
            }
            return sum;

        }else{
            long middle=(start+end)/2;
            ForkJoinTest task1 = new ForkJoinTest(start, middle);
            task1.fork();  //拆分任务,把任务压入线程队列
            ForkJoinTest task2 = new ForkJoinTest(middle + 1, end);
            task2.fork();

            return task1.join()+task2.join();  //返回结果
        }
    }
}

测试类

public class Test {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        test3();
    }
    //普通方式
    //sum=500000000500000000 时间:3594
    public static void test1(){
        long sum=0L;
        long start=System.currentTimeMillis();
        for(Long i=1L;i<=10_0000_0000;i++){
            sum=sum+i;
        }
        long end=System.currentTimeMillis();

        System.out.println("sum="+sum+" 时间:"+(end-start));
    }
    //ForkJoin
    //sum=500000000500000000 时间:4256  可以调节
    public static void test2() throws ExecutionException, InterruptedException {

        long start=System.currentTimeMillis();

        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTest task = new ForkJoinTest(0L, 10_0000_0000L);
        //forkJoinPool.execute(task);  //执行任务 同步
        ForkJoinTask<Long> submit = forkJoinPool.submit(task);//提交任务 异步
        Long sum = submit.get();

        long end=System.currentTimeMillis();
        System.out.println("sum="+sum+" 时间:"+(end-start));
    }
    //Stream并行流
    //sum=500000000500000000 时间:234  最优方案
    public static void test3(){
        long start=System.currentTimeMillis();


        long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0L, Long::sum);

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

ForkJoin必须是在大数据量时使用

posted @ 2022-01-17 17:00  一刹流云散  阅读(35)  评论(0编辑  收藏  举报