JUC并发编程(九)-- Fork/Join框架

JUC并发编程(九)-- Fork/Join框架

    • 一、什么是Fork/Join
      • 1、概述
      • 2、特点
    • 二、代码实现

一、什么是Fork/Join

1、概述

fork/join 框架可以将一个大任务,拆分成一个个的小任务,然后分别计算,将得到的结果相加后,给出一个完整的结果。
JUC并发编程(九)-- Fork/Join框架_第1张图片

2、特点

fork/join还有一个特点,叫:工作窃取。
什么是工作窃取??
有这样一个场景,有两个线程A和B,都分配了四个任务,A线程刚刚执行了一个任务,而B线程已经执行完了分配给它的四个任务,那么这个时候,通常情况下,B线程就会无事可做,而A线程就会继续执行剩下的三个任务,而fork/join 框架下,则会让B线程去盗取A线程的任务,给A线程帮忙,做剩下的任务。

二、代码实现

首先自己定义一个任务类:

package com.zhan.juc.forkjoin;

import java.util.concurrent.RecursiveTask;

/**
 * @Author Zhanzhan
 * @Date 2020/12/21 20:30
 */
public class ForkJoinDemo extends RecursiveTask<Integer> {

    private static final long serialVersionUID = 1L;

    private static final long THRESHOLD = 1000; // 临界值,达到此值就拆分任务

    private int start; // 子任务开始的边界
    private int end; // 子任务结束的边界

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

    @Override
    protected Integer compute() {
        if ((end - start) <= THRESHOLD) { // 进行计算
            int sum = 0;
            for (int i = start; i <= end; i++) {
                sum += i;
            }
            return sum;
        } else { // 拆分任务
            int mid = (start + end) / 2; // 将边界值一分为二,其实和归并排序的思想类似,也是种递归
            ForkJoinDemo task1 = new ForkJoinDemo(start, mid);
            ForkJoinDemo task2 = new ForkJoinDemo(mid + 1, end);
            invokeAll(task1, task2);
            return task1.join() + task2.join();
        }
    }
}

然后还有测试类:

package com.zhan.juc.forkjoin;

import java.util.OptionalInt;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.stream.IntStream;

/**
 * @Author Zhanzhan
 * @Date 2020/12/21 20:54
 */
public class Test {

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

    /**
     * 用for循环 来计算
     */
    public static void test1() {
        int sum = 0;
        long start = System.currentTimeMillis();
        for (int i = 0; i <= 1000000000; i++) {
            sum += i;
        }
        long end = System.currentTimeMillis();
        System.out.println("sum=" + sum + ",耗费的时间为:" + (end - start) + "毫秒");
    }

    /**
     * 使用 fork/join 来计算
     */
    public static void test2() throws ExecutionException, InterruptedException {
        long start = System.currentTimeMillis();
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        ForkJoinTask<Integer> submit = forkJoinPool.submit(new ForkJoinDemo(0, 1000000000));
        long sum = submit.get();
        long end = System.currentTimeMillis();
        System.out.println("sum=" + sum + ",耗费的时间为:" + (end - start) + "毫秒");
    }

    /**
     * 使用 stream 并行流
     */
    public static void test3() {
        long start = System.currentTimeMillis();
        OptionalInt result = IntStream
                .rangeClosed(0, 1000000000)
                .parallel()
                .reduce(Integer::sum);
        long end = System.currentTimeMillis();
        System.out.println("sum=" + result.getAsInt() + ",耗费的时间为:" + (end - start) + "毫秒");
    }
}

结果如下:
JUC并发编程(九)-- Fork/Join框架_第2张图片

你可能感兴趣的:(多线程,java,java,多线程,并行计算,并发编程,forkjoin)