Java并发——Fork/Join框架原理解析

前言

最近有个哥们问我一个实际项目的问题,大致如下:需要给一个目录下的所有文件的路径生成对应的MD5签名。这个哥们首先想到的是采用递归的方式处理,这个思路是没问题的,但是完全没有必要自己造轮子。因为Java已经提供了成熟的工具可以使用了,那就是Fork/Join并行执行任务框架。基于此契机,本篇文章将记录自己理解Fork/Join框架原理的心得。

在JDK1.7版本中,J.U.C包迎来了新的成员Fork/Join并行执行任务框架。Fork/Join框架的思想其实就是分而治之的思想。

什么是Fork/Join框架?

我们通过Fork和Join这两个单词来理解它。Fork就是把一个大任务分解成若干个子任务,然后并行执行这些子任务,从这里可以看到,子任务是一个独立的任务,它们互不影响但又都是大任务下的一部分;Join就是把这个子任务执行的结果汇总。最终得到大任务的结果。下面这张图就是Fork/Join运行的流程图:

Fork Join运行的流程图

Fork/Join框架的设计思路

基于以上介绍,如果让你来实现一个类似功能的框架,应该怎么来设计呢?借助这个问题的思考来一探Fork/Join框架的设计思路。
分割任务:首先,我们需要一个fork类将大任务分割成子任务,然而,子任务依然可能很大,因此还要继续分割子任务直到任务粒度足够小。
执行任务合并结果:分割的任务分别放到双端队列中,然后启动几个线程,分别从双端队列中获取任务来执行任务,执行的结果放到另一个队列中,由一个线程来合并执行的结果。
在Fork/Join框架中,提供了两个类来完成以上两个步骤。

  • ForkJoinTask
    在使用Fork/Join框架,必须要先创建一个ForkJoin任务。ForkJoinTask便提供了这个能力,并且提供了fork()和join()的工作机制。通常情况下,我们不需要继承ForkJoinTask,而是继承它的子类来完成我们的实际需求。它有两个子类区别如下:
类名 说明
RecursiveAction 用于没有返回结果的任务
RecursiveTask 用于有返回结果的任务
  • ForkJoinPool
    ForkJoinTask需要通过ForkJoinPool来执行。分割的子任务会被添加到当前工作线程所维护的双端队列中,当一个工作线程的队列中暂时没有任务时,会从其他工作线程的队列尾部窃取任务来执行。

使用Fork/Joink框架

接下来,我们基于以上的介绍来实际使用一把Fork/Join框架来计算1+2+3+…+100。

public class ForkJoinTest {
   

    public static void main(String[] args) throws ExecutionException, InterruptedException {
   
        // 创建ForkJoinPool,指定并发线程数
        ForkJoinPool forkJoinPool = new ForkJoinPool(2);
        // 创建目标任务
        MyAddTask myAddTask = new MyAddTask
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值