J.U.C之ForkJoin

本文深入解析Java7中的ForkJoin框架,介绍其工作原理、任务分割与聚合机制,以及如何通过实例代码实现累加求和操作。ForkJoin采用工作窃取模式,将大任务分解为小任务并行执行,最后合并结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本章简说一下ForkJoin

ForkJoin是Java7提供的原生多线程并行处理框架,其基本思想是将大人物分割成小任务,最后将小任务聚合起来得到结果。Fork/Join采用“工作窃取模式”,当执行新的任务时他可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随即线程中偷一个并把它加入自己的队列中
Fork就是把一个大任务切分为若干子任务并行的执行,Join就是合并这些子任务的执行结果,最后得到这个大任务的结果。比如计算1+2+。。+10000,可以分割成10个子任务,每个子任务分别对1000个数进行求和,最终汇总这10个子任务的结果
在这里插入图片描述
我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join的操作机制,通常我们不直接继承ForkjoinTask类,只需要直接继承其子类。

  1. 继承RecursiveAction,用于没有返回结果的任务;
  2. 继承RecursiveTask,用于有返回值的任务。

ForkJoinPool:task要通过ForkJoinPool来执行,分割的子任务也会添加到当前工作线程的双端队列中,进入队列的头部。当一个工作线程中没有任务时,会从其他工作线程的队列尾部获取一个任务。

下面看一个累加求和的例子:

import java.util.concurrent.*;

public class ForkJoinTest extends RecursiveTask<Integer> {

    private static final int thresheld = 2;

    private int start;

    private int end;

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

    @Override
    protected Integer compute() {
        int sum = 0;

        boolean flag = (end - start) <= thresheld;
        //如果未执行的任务数量小于等于了线程数量,则表示未完成的任务很少了,可以直接进行计算
        if(flag){
            for(int i = start; i <= end; i++){
                sum += i;
            }
        }else{          //如果未执行的任务数量大于等于了线程数量,则表示未完成的任务还有很多,使用ForkJoin
            int middle = (start + end) / 2;     //平均分配任务数量
            ForkJoinTest forkJoinTest1 = new ForkJoinTest(start, middle);       //执行前半部分的任务
            ForkJoinTest forkJoinTest2 = new ForkJoinTest(middle + 1, end);       //执行后半部分的任务

            //开始执行子任务
            forkJoinTest1.fork();
            forkJoinTest2.fork();

            //得到结果
            int res1 = forkJoinTest1.join();
            int res2 = forkJoinTest2.join();

            sum = res1 + res2;
        }

        return sum;
    }

    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();

        ForkJoinTest task = new ForkJoinTest(1, 1000);//计算1-100的和

        Future<Integer> result = forkJoinPool.submit(task); //执行这个任务

        try {
            System.out.printf(result.get().toString());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

我比较喜欢把解释写在代码注释里,大家看代码哈
个人浅薄理解,欢迎补充

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值