彻悟并发之JUC分支思想产物-ForkJoin分支合并框架原理剖析

引言

本文详细谈谈JDK1.7中新推出的线程池:ForkJoinPool。但ForkJoinPool的出现并不是为了替代ThreadPoolExecutor,而是作为它的补充,因为在某些场景下,它的性能会比ThreadPoolExecutor更好。在之前的模式中,往往一个任务会分配给一条线程执行,如果有个任务耗时比较长,并且在处理期间也没有新的任务到来,那么则会出现一种情况:线程池中只有一条线程在处理这个大任务,而其他线程却空闲着,这会导致CPU负载不均衡,空闲的处理器无法帮助工作,从而无法最大程度上发挥多核机器的性能。而ForkJoinPool则可以完美解决这类问题,但ForkJoinPool更适合的是处理一些耗时的大任务,如果是普通任务,反而会因为过多的任务拆分和多条线程CPU的来回切换导致效率下降。

一、初窥ForkJoin框架的神秘面纱

ForkJoinPool是一个建立在分治思想上的产物,其采用任务“大拆小”的方式以及工作窃取算法实现并行处理任务。通俗来说,ForkJoin框架的作用主要是为了实现将大型复杂任务进行递归的分解,直到任务小到指定阈值时才开始执行,从而递归的返回各个小任务的结果汇集成一个大任务的结果,依次类推最终得出最初提交的那个大型复杂任务的结果,这和方法的递归调用思想是一样的。当然ForkJoinPool线程池为了提高任务的并行度和吞吐量做了非常多而且复杂的设计实现,其中最著名的就是任务窃取机制。但ForkJoinPool更适合于处理一些大型任务,因此,ForkJoinPool的适用范围不大,仅限于某些密集且能被分解成多个子任务的任务,同时这些子任务运行的结果可以合并成最终结果。ForkJoin框架主体由三部分组成:

  • ①ForkJoinWorkerThread:任务的执行者,具体的线程实体
  • ②ForkJoinTask:需要执行的任务实体
  • ③ForkJoinPool:管理执行者线程的管理池

后续源码阶段会详细分析!

OK~,接着先简单的来看看ForkJoin框架的使用,ForkJoinPool提交任务的方式也有三种,分别为:

  • execute():可提交Runnbale类型的任务
  • submit():可提交Callable类型的任务
  • invoke():可提交ForkJoinTask类型的任务,但ForkJoinTask存在三个子类: ①RecursiveAction:无返回值型ForkJoinTask任务 ②RecursiveTask:有返回值型ForkJoinTask任务 ③CountedCompleter:任务执行完成后可以触发钩子回调函数的任务

上个案例:

业务需求:需要根据ID值对某个范围区间内的每条数据进行变更,变更后获取最新数据更新缓存。
运行环境:四核机器

案例如上,在其中模拟了数据库查询1000W数据后,将数据添加到集合中的操作。其中定义了任务类:IdByFindUpdate,因为需要返回结果,所以IdByFindUpdate类实现了ForkJoinTask的子类RecursiveTask,确保任务可以提交给ForkJoinPool线程池执行。任务的拆分阈值设定为1W,当任务的查询数量小于阈值时,则直接执行任务。反之,拆分任务直至最小(达到阈值)为止才开始执行,执行结束后合并结果并返回。

同时,我们为了对比区别,也使用了普通的for循环来对比测试,结果如下:

很明显,ForkJoin的执行速度比普通的for循环速度快上三倍左右,但是值得一提的是:如果任务的量级太小,ForkJoin的处理速度反而比不上普通的For循环。这是因为ForkJoin框架在拆分任务fork阶段于合并结果join阶段需要时间,并且开启多条线程处理任务,CPU切换也需要时间,所以当一个任务fork/join阶段以及CPU切换的时间开销大于原本任务的执行时间时,这种情况下则没有必要使用ForkJoin框架。

注意:ForkJoin的执行时间跟机器硬件配置以及拆分临界值/阈值的设定也有关系,拆分的阈值并不是越小越好,因为阈值越小时,一个任务拆分的小任务也就会越多,而拆分、合并阶段都是需要时间的,所以阈值需要根据机器的具体硬件设施和任务的类型进行合理的计算,这样才能保证任务执行时能够到达最佳状态。

ok,我也做了一个比较有意思的小测试,把单线程for循环的模式来处理上述任务以及ForkJoin框架处理上述任务分别分为了两次来执行,同时监控了CPU的利用率状况,具体如下:

通过上图可以非常清晰的看见,当单线程for循环的模式处理任务时,因为是在多核机器上执行,所以对于CPU的利用率最高不到50%,而当使用ForkJoin框架处理任务时,几次触顶达到了100%的CPU利用率。所以我们可以得出一个结论:ForkJoin框架在处理任务时,能够在最大程度上发挥机器的性能。

二、ForkJoin框架原理浅析及成员构成

在如上,对于ForkJoin框架已经建立的初步的认知,接着慢慢继续分析其内部实现过程。

2.1、ForkJoin框架原理

在前面提到过,ForkJoin框架是建立在分治思想上的产物,而向F

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值