27、JUC:ForkJoin入门

学习过程观看视频:[狂神说Java]
https://www.bilibili.com/video/BV1B7411L7tE?p=13
欢迎大家支持噢,很良心的老师了!

1、什么是ForkJoin?

27、JUC:ForkJoin入门_第1张图片
27、JUC:ForkJoin入门_第2张图片

2、ForkJoin 特点:工作窃取

这个里面维护的都是双端队列。27、JUC:ForkJoin入门_第3张图片

3、ForkJoin

在这里插入图片描述
27、JUC:ForkJoin入门_第4张图片

java代码示例:

package com.function;

import jdk.nashorn.internal.ir.CallNode;

import java.util.concurrent.RecursiveTask;

/*** 求和计算的任务!
 * 3000  6000(ForkJoin) 9000(Stream并行流)
 * // 如何使用 forkjoin
 * // 1、forkjoinPool 通过它来执行
 * // 2、计算任务 forkjoinPool.execute(ForkJoinTask task)
 * // 3. 计算类要继承 ForkJoinTask
 */
public class ForkJoinDemo extends RecursiveTask<Long> {

    private Long start;
    private Long end;

    //临界值,使用ForkJoin进行求和计算
    private Long temp = 10000L;

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

    //计算方法
    @Override
    protected Long compute() {
        if((end - start) < temp){   //当两数相减小于临界值时,使用正常计算求和方式
            Long sum = 0L;
            for (Long i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        }else {   // forkjoin 递归
            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();
        }
    }
}

测试类:

package com.function;

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

/**
 * Created by zjl
 * 2020/11/29
 **/
public class ForkJoinDemoTest {

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        test1();
    }

    //常规求和方式
    public static void test1(){
        Long sum = 0L;
        Long startTime = System.currentTimeMillis();
        for (int i = 0; i <= 10_0000_0000; i++) {
            sum += i;
        }
        System.out.println(sum);
        long endTime = System.currentTimeMillis();
        System.out.println("运行时间" + (endTime/1000 - startTime/1000) + "秒");
    }

    //使用ForkJoin
    public static void test2() throws ExecutionException, InterruptedException {
        long startTime = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinDemo forkJoinDemo = new ForkJoinDemo(0L, 10_0000_0000L);
        ForkJoinTask<Long> submit = forkJoinPool.submit(forkJoinDemo);   //提交任务

        Long sum = submit.get();
        System.out.println(sum);
        long endTime = System.currentTimeMillis();
        System.out.println("运行时间" + (endTime/1000 - startTime/1000) + "秒");
    }

    public static void test3(){
        long startTime = System.currentTimeMillis();
        // parallel()并行执行,Long::sum就是(l1,l2)->{return Long.sum(l1,l2)}
        //reduce方法用于对stream中元素进行聚合求值,最常见的用法就是将stream中一连串的值合成为单个值,比如为一个包含一系列数值的数组求和
        long sum = LongStream.rangeClosed(0L, 10_0000_0000L).parallel().reduce(0, Long::sum);
        System.out.println(sum);
        long endTime = System.currentTimeMillis();
        System.out.println("运行时间" + (endTime/1000 - startTime/1000) + "秒");

    }
}

运行结果分别为:

test1()方法:
27、JUC:ForkJoin入门_第5张图片
test2()方法:
27、JUC:ForkJoin入门_第6张图片
test3()方法:
27、JUC:ForkJoin入门_第7张图片
注意:可能因为我电脑配置的原因,而数据量有不足够大,导致常规求和方式比使用ForkJoin要快。我们真正使用ForkJoin的时候,需要多次进行调试选出最优方案。

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