Java并发之Fork-Join框架

点击上方蓝字关注的都是靓仔和仙女


1什么是Fork/Join框架 及产生背景


        Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。上边是书上的定义。


        我们用粗话说:Fork/Join是一个框架,来解决执行效率,手段是并行,但是是拆分型的并行!则,如果一个应用能被分解成多个子任务,并且组合多个子任务的结果就能够获得最终的答案,那么这个应用就适合用 Fork/Join 模式来解决。


产生背景:


        多核处理器已广泛应用要提高应用程序在多核处理器上的执行效率,只能想办法提高应用程序的本身的并行能力。常规的做法就是使用多线程,让更多的任务同时处理,或者让一部分操作异步执行,这种简单的多线程处理方式在处理器核心数比较少的情况下能够有效地利用处理资源,因为在处理器核心比较少的情况下,让不多的几个任务并行执行即可。但是当处理器核心数发展很大的数目,上百上千的时候,这种按任务的并发处理方法也不能充分利用处理资源,因为一般的应用程序没有那么多的并发处理任务(服务器程序是个例外)。所以,只能考虑把一个任务拆分为多个单元,每个单元分别得执行最后合并每个单元的结果,而fork/join框架就是为这而生的,java7中才认识到了这个问题。


2工作窃取(work-stealing)算法


        了解这个框架之前我们需要了解一下这其中最终要的算法--工作窃取算法。工作窃取算法是指某个线程从其他队列里窃取任务来执行。工作窃取的运行流程图如下 

        下边介绍的工作窃取算法的定义我会把我认为重要的东西标记出来,大家着重看一下:


        那么为什么需要使用工作窃取算法呢?假如我们需要做一个比较大的任务,我们可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,于是把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应,比如A线程负责处理A队列里的任务。但是有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。


        工作窃取算法的优点是充分利用线程进行并行计算,并减少了线程间的竞争,其缺点是在某些情况下还是存在竞争,比如双端队列里只有一个任务时。并且消耗了更多的系统资源,比如创建多个线程和多个双端队列。


3Fork/Join框架的设计


        设计整个框架主要包括两个步骤:

        (1)分割任务

        分割任务主要指的是将一个fork大类分割成小的任务,但是这些小的任务可能还是很大,所以要不停的分割,直到任务足够小。


        (2)执行任务,合并结果

        刚才我们说到,不同的任务对应不通的双端队列,这样的话几个不同的队列分别从各自的双端队列中执行任务,子任务执行完成之后将结果都统一的放在一个队列中,这时候启动一个线程从队列里边拿数据,然后将这些数据合并。


        说了这么多定义,那么Fork/Join到底是如何工作呢,好  下边我们来看主要用到的类:


        ForkJoinTask:我们要执行ForkJoin任务就要创建一个ForkJoinTask任务,这个任务提供fork(),join()机制,通常状况下,我们不需要直接继承ForkJoinTask任务,只需继承他的子类就可以了,框架提供了下边两个子类:

RecursiveAction:用于没有返回结果的任务

RecursiveTask:用于有返回结果的任务


4、Fork/Join框架的异常处理


        ForkJoinTask在执行的时候可能会抛出异常,但是我们没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常。使用如下代码:

if(task.isCompletedAbnormally())

{

    System.out.println(task.getException());

}

getException方法返回Throwable对象,如果任务被取消了则返回CancellationException。如果任务没有完成或者没有抛出异常则返回null。


5使用场景


        工作中可能会遇到的使用场景:

        (1)有大量计算工作的程序,可以将这些计算分别fork之后join

        (2)处理大文件,处理大文件的时候我们可以将大文件分割开来,分别处理,最后结果汇总。

        (3)处理海量的数据库的程序,因为访问数据库每次消耗性能最大的就是io,访问次数多了,性能就会急剧下降,这样的话我们分开处理,最后汇总结果,可以并发执行。

        (4)高并发的消息队列

        暂时想到这些,当然工作中远不止这些应用场景。

        (5)处理排序算法,具体大家可以看看这个人写的文章,很不错,快排,归并,和桶排序都有分析:http://blog.csdn.net/yinwenjie/article/details/72828691


6、约束条件

        (1)除了fork() 和 join()方法外,线程不得使用其他的同步工具。线程最好也不要sleep()

        (2)线程不得进行I/O操作

        (3)线程不得抛出checked exception


7和普通的多线程相比有什么优势。


        有人说了,想从1+2+3+。。100  这样的程序用普通的多线程也可以实现,是的可以实现,但是fork/join和ThreadPoolExecutor 相比会有什么优势呢?


        (1)代码量的问题,fork/join已经是集成的代码,我们拿来直接使用即可,不用自己在写好多代码做判断。

        (2)从分治的算法思想到fork/join框架,这种并行性的的融入可以更加高效率的解决一大批的问题。和我们一些传统的多线程应用方式如ThreadPoolExecutor比起来,它有一些自己的特点。一个典型的地方就是work-stealing,它的一个优点是在传统的线程池应用里,我们分配的每个线程执行的任务并不能够保证他们执行时间或者任务量是同样的多,这样就可能出现有的线程完成的早,有的完成的晚。在这里,一个先完成的线程可以从其他正在执行任务的线程那里拿一些任务过来执行。我们可以说这是人家学习雷锋好榜样。这样发挥主观能动性的线程框架肯定办起事来就效率高了。


8、总结

        fork-join 方法提供了一种表示可并行化算法的简单方式。所有的排序、搜索和数字算法都可以进行并行分解。随着处理器数量的增长,我们将需要在程序内部使用更多的并行性,以有效利用这些处理器;我在这个fork/join框架中看到的还是分支的思想,就像对三大排序算法,归并排序,堆排序,快排等,都是分治的思想,希望大家可以仔细琢磨,对这个框架起码到会用的状态,有可能会大大提升你的工作效率。





 更加具体的 fork-join用法及技术点 

会在今晚8:30



腾讯课堂

动脑学院的

Java高级免费试听中

由我们的Mark老师来给大家

详细的进行解说



不容错过的精彩内容

而你只需在今晚8:30

点击最下方

阅读原文

即可观看



  老师简介  



  所受课程介绍



  部分学生听课反馈 


  推荐阅读  

dubbo核心技术原理:RPC调用协议

系统安全卫士企业级安全架构shiro源码分析

高并发与分布式系统的基石--数据库读写分离实战

这就是学编程的下场...

论程序员与产品经理是怎么互掐起来的

如何假装成为一名好的程序员

来自部落的邀请

Java框架 Spring 核心机制

至程序员的情书

Java高级部落送你ofo小黄车60天免费骑行,还不来?

Facebook研发的Cassandra你用过吗?

给 Java开发者的10个大数据工具和框架


推荐程序员必备微信号 

Java高级部落

微信号:javagaojibuluo



在部落里,将会分享程序员相关的的技术,职场生活,行业热点资讯....以及更多好玩的IT趣文和趣图都在此部落中.....这....只属于我们程序猿.....


 ▼长按下方↓↓↓二维码识别关注

推荐学习资料获取微信号 

长按下方二维码识别关注


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值