ForkJoinPool分支/合并框架

在必要的情况下,讲一个大任务,进行拆分(fork)成若干个小任务(拆到不可拆为止),再将一个个小的任务运算的结果进行join汇总。

工作窃取的背景

分支/合并框架,里面提到了ForkJoinSumCalculator会将一个任务分成很多个子任务,一般来说分出大量的子任务是个好的选择。因为在理想的情况下,划分并行任务时,应该要让每个任务都用完全相同的时间完成,让所有的CPU内核都同样繁忙。但是实际中,每个子任务所花费的时间可能天差地别,要么因为划分策略低,要么因为不可预知的原因,比如磁盘访问慢,或者需要和外部服务协调执行。

工作窃取的使用

针对多个线程分配相同多子任务的时候,会出现不同线程完成所有任务的时间有快有慢的情况,分支/合并框架工程使用了工作窃取的技术来解决这个问题。在实际应用中,这些子任务被差不多的分配到ForkJoinSumCalculator中的所有线程上,每个线程都为分配给他的任务保存一个双向的链式队列,每完成一个任务,就会队列头上取出下一个任务开始执行。因为上面所述的原因,有些线程可能早早地完成了分配给他的任务,也就是他的队列已经空了,但其他的线程还是很忙。这个时候队列已经空了的线程并不会闲置下来,而是随机选择一个其他的线程从队列的尾巴上“偷走”一个任务。这个过程会一直继续下去,知道所有的任务都执行完毕,所有的队列都清空。这就是为什么要划成许多小任务而不是少数几个大任务的原因,他能有助于工作线程之间的平衡负载。

工作窃取算法的过程

当工作线程队列中有一个任务被分成两个子任务时,一个子任务就被闲置的工作线程给“偷走”了,这个过程可以不断的递归,直到规定子任务应顺序执行的条件为真。下图展示了工作窃取算法用于在池中的工作线程之间重新分配和平衡任务的过程。

总结

相比一般的线程池实现,ForkJoinPool分支/合并框架在对其中包含的任务的处理方式上具有优势,在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而在ForkJoinPool分支/合并框架上,如果某个子问题由于等待另外一个子问题的完成而无法继续运行,那么处理该子问题的线程会主动寻找其他尚未运行的子问题(窃取过来)来执行,这种方式而减少了线程池的等待时间,提高了性能。

ps:写个博客记录一下自己学习的东西,如有错误请指出,万分感谢。

ForkJoinPool分支/合并框架工程使用的工作窃取的更多相关文章

  1. 11.ForkJoinPool 分支/合并框架 (工作窃取)

    /*ForkJoinPool 分支/合并框架 (工作窃取)*/ Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork) 成若干个小任务(拆到给出的临界值为止),再将一个个的小 ...

  2. ForkJoinPool 分支/合并框架

    ForkJoinPool 分支/合并框架 一.Fork/Join框架简介 Fork/Join 框架就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小 ...

  3. java多线程 -- ForkJoinPool 分支/ 合并框架 工作窃取

    Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总. Fork/Join 框架与线程池的 ...

  4. ForkJoinPool分支合并框架-工作窃取

    Fork/Join 框架 Fork/Join 框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成 若干个小任务(拆到不可再拆时), 再将一个个的小任务运算的结果进行 join 汇总 For ...

  5. TortoiseGit- 创建本地新分支,提交推送到远程,本地新分支合并到工作分支,提交到远程工作分支等。

    整体思路: 创建本地新分支 (create branch)  -- 切换到本地新分支工作 (switch/checkout) --提交修改 (commit)  -- 推送到远程新分支 (push)  ...

  6. JUC---08ForkJion(分支合并)

    一.什么是ForkJion Fork/Join框架是Java7提供的并行执行任务框架,思想是将大任务分解成小任务,然后小任务又可以继续分解,然后每个小任务分别计算出结果再合并起来,最后将汇总的结果作为 ...

  7. 关于SVN版本分支合并的知识

    分支的合并类型 合并的工作是把主干或者分支上合并范围内的所有改动列出,并对比当前工作副本的内容,由合并者手工修改冲突,然后提交到服务器的相应目录里.如果当前工作副本是主干,则合并的范围是分支上的改动, ...

  8. TortoiseSVN 的分支合并操作

    今天对svn的分支合并有了兴趣,所以对新建了一个项目练练手. 在网上找了一篇文章做指导: http://www.open-open.com/lib/view/open1346982569725.htm ...

  9. Git分支合并选择

    用Git进行多人协作开发时,必然会合并代码,解决冲突.然而合并代码也是需要点技巧的,如果对一些关键命令没有理解去使用的话,git的版本演进路线就会变得很乱,从而造成了日后维护的一些麻烦. Git上合并 ...

随机推荐

  1. 关于EF ORM 框架的使用问题

    1.无法更新 EntitySet“System_UserInfo20140218001”,因为它有一个 DefiningQuery,而 <ModificationFunctionMapping& ...

  2. Play Framework 模板里使用注入访问数据层

    从Play2.4开始,推荐使用依赖注入替代静态控制器.因此我们不能像play2.3那样,在模板里直接调用object访问数据层.是的,我们还是可以使用常规方式,通过传参到模板里.不过这样很多时候不方便 ...

  3. 访问类的私有属性(RTTI和模仿类2种方法)

    如何访问类的私有属性? 下面以 TPathData 为例,它有一个私有属性 PathData,储存了每一个曲线点,但一般无法修改它,需要利用下面方法,才能访问修改(若有更好的方法,歡迎分享): 一.利 ...

  4. 一次项目代码重构-使用spring容器干掉条件判断

    一次项目代码重构-使用spring容器干掉条件判断 这是在一次公司项目中进行重构时,一些复杂业务时想到的一个去掉一些if else的办法.能够使代码逻辑更加清晰,减少一些业务上的耦合. 业务说明 我所 ...

  5. mogodbshell中数组对象查询修改方法

    在mongodb中,存在如下数据 { "_id" : ObjectId("59af55078a8fc5e51ff425de"), "title&quo ...

  6. Spring Boot:实现MyBatis动态数据源

    综合概述 在很多具体应用场景中,我们需要用到动态数据源的情况,比如多租户的场景,系统登录时需要根据用户信息切换到用户对应的数据库.又比如业务A要访问A数据库,业务B要访问B数据库等,都可以使用动态数据 ...

  7. c/c++基础内容回顾

    1.1基本数据类型 1.1.1 变量的定义 变量类型 变量名 变量类型 变量名=初值: 注意:不能以C语言标识符作为变量名,变量名的第一个字符必须是字母或者下划线,其它位置字符必须是字母.数字.下划线 ...

  8. Fabric1.4源码解析:Peer节点加入通道

          又开始新的阅读了,这次看的是Peer节点加入通道的过程.其实每次看源码都会有好多没有看懂的地方,不过相信只要坚持下去,保持记录,还是有很多收获的.       对于Peer节点加入通道这一 ...

  9. PATA 1006. Sign In and Sign Out (25)

    #include <bits/stdc++.h> using namespace std; const int N = 100005; struct visitor{ char ID[20 ...

  10. Java基础知识了解

    第一章 开发前言 一.java语言概述 Java是当下最流行的一种编程语言,至今有20年历史了.Java语言之父是James Gosling. Java是Sun公司(Stanford Universi ...