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

Fork/Join 框架与线程池的区别

  1. 采用 “工作窃取”模式(work-stealing):当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。
  2. 相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上.在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态。而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行。那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行.这种方式减少了线程的等待时间,提高了性能。

ForkJoinPool封装类:

  1. package com.company;
  2.  
  3. import java.util.concurrent.Callable;
  4. import java.util.concurrent.ExecutionException;
  5. import java.util.concurrent.ForkJoinPool;
  6. import java.util.concurrent.ForkJoinTask;
  7.  
  8. public final class ForkJoinPoolUtils {
  9.  
  10. private static final int CPUS_COUNT = Runtime.getRuntime().availableProcessors();
  11.  
  12. private ForkJoinPoolUtils(){}
  13.  
  14. public static <T> T executeInDedicatedThreadPool(Callable<T> task){
  15. return executeInDedicatedThreadPool(task, CPUS_COUNT);
  16. }
  17. public static <T> T invokeInDedicatedThreadPool(ForkJoinTask<T> task){
  18. return new ForkJoinPool(CPUS_COUNT).invoke(task);
  19. }
  20.  
  21. public static <T> T executeInDedicatedThreadPool(Callable<T> task, int threadsCount){
  22. try{
  23. return new ForkJoinPool(threadsCount).submit(task).get();
  24. }
  25. catch( ExecutionException execEx ){
  26. throw new IllegalStateException(execEx);
  27. }
  28. catch(InterruptedException interEx ){
  29. Thread.currentThread().interrupt();
  30. throw new IllegalStateException(interEx);
  31. }
  32. }
  33.  
  34. }

使用forkJoinPool Demo:

  1. package com.company;
  2.  
  3. import java.time.Duration;
  4. import java.time.Instant;
  5. import java.util.concurrent.ForkJoinTask;
  6. import java.util.concurrent.RecursiveTask;
  7.  
  8. public class TestForkJoinPool {
  9.  
  10. public static void main(String[] args) {
  11. Instant start = Instant.now();
  12. ForkJoinTask<Long> task = new ForkJoinSumCalculate(0L, 500000000L);
  13. Long sum = ForkJoinPoolUtils.invokeInDedicatedThreadPool(task);
  14. System.out.println(sum);
  15. Instant end = Instant.now();
  16. System.out.println("耗费时间为:" + Duration.between(start, end).toMillis());//166-1996-10590
  17. }
  18.  
  19. }
  20.  
  21. class ForkJoinSumCalculate extends RecursiveTask<Long> {
  22.  
  23. private static final long serialVersionUID = -259195479995561737L;
  24. private long start;
  25. private long end;
  26. private static final long THURSHOLD = 10000L; //临界值
  27.  
  28. public ForkJoinSumCalculate(long start, long end) {
  29. this.start = start;
  30. this.end = end;
  31. }
  32.  
  33. @Override
  34. protected Long compute() {
  35. long length = end - start;
  36.  
  37. if (length <= THURSHOLD) {
  38. long sum = 0L;
  39. for (long i = start; i <= end; i++) {
  40. sum += i;
  41. }
  42. return sum;
  43. } else {
  44. long middle = (start + end) / 2;
  45. ForkJoinSumCalculate left = new ForkJoinSumCalculate(start, middle);
  46. left.fork(); //进行拆分,同时压入线程队列
  47. ForkJoinSumCalculate right = new ForkJoinSumCalculate(middle + 1, end);
  48. right.fork(); //
  49. return left.join() + right.join();
  50. }
  51. }
  52.  
  53. }

结果:

  1. 125000000250000000
  2. 耗费时间为:204

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

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

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

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

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

  3. ForkJoinPool 分支/合并框架

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

  4. ForkJoinPool分支/合并框架工程使用的工作窃取

    ForkJoinPool分支/合并框架 在必要的情况下,讲一个大任务,进行拆分(fork)成若干个小任务(拆到不可拆为止),再将一个个小的任务运算的结果进行join汇总. 工作窃取的背景 分支/合并框 ...

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

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

  6. java多线程系列:Executors框架

    目录 Executor接口介绍 ExecutorService常用接口介绍 创建线程池的一些方法介绍 3.1 newFixedThreadPool方法 3.2 newCachedThreadPool方 ...

  7. JAVA多线程(四) Executor并发框架向RabbitMQ推送消息

    github代码地址: https://github.com/showkawa/springBoot_2017/tree/master/spb-demo/spb-brian-query-service ...

  8. java 多线程 一个博客

    http://blog.csdn.net/a352193394/article/category/2563875 Java多线程之~~~线程安全容器的非阻塞容器 在并发编程中,会经常遇到使用容器.但是 ...

  9. JUC-分支合并框架

    一.原理 Fork:把一个复杂任务进行分拆,大事化小 Join:把分拆任务的结果进行合并 ForkJoinPool 分支合并池    类比=>   线程池 ForkJoinTask ForkJo ...

随机推荐

  1. bootstrap轮播图不能显示左右箭头

    引入font文件夹即可 原文 :http://www.imooc.com/qadetail/64277

  2. 基础业务:滚动到指定位置导航固定(CSS实现)

    最近公司做的业务都是使用Vue.Element写的,涉及到的相应的基础业务像轮播.预加载.懒加载,都是使用 NPM上的工具来实现,原理和基础还是要有的,就来实现几个项目中常用到的业务. 经常见到这样的 ...

  3. UVALive 7464 Robots(模拟)

    7464Robots Write a program to collect data from robots. We are given two sets of robotsX=fX1;:::;Xmg ...

  4. [2019BUAA软工]第0次代码作业

    Visual Studio 单元测试的简单应用 写在前面   笔者根据作业的介绍以及Visual Studio 2017 文档的相关说明,进行了Visual Studio 单元测试的简单应用. Tip ...

  5. Hibernate笔记②--hibernate类生成表、id生成策略、级联设置、继承映射

    一.多表的一个关联关系 老师和学生是一对多的关系 student:tid属性 外键约束 对应teacher表中的id属性 teacher:id 在myeclipse的db窗口中选中两个表来生成类.   ...

  6. BNUOJ 52303 Floyd-Warshall Lca+bfs最短路

    题目链接: https://www.bnuoj.com/v3/problem_show.php?pid=52303 Floyd-Warshall Time Limit: 60000msMemory L ...

  7. 第一次spring冲刺第8天

    针对这几天出现的问题,我们团队做了用户需求讨论. 1.客户类型:工作者为主,其他类型都适用的计算器软件 2.需求与满足:他们想要的是能使用简单,并且适用于工作上 3.满足度:最好后台可以提供意见反馈, ...

  8. git学习-综合性文章

    文章:[转载]理解 Git 分支管理最佳实践 首先介绍了git各种分支:

  9. IHttpModule理解-知识补充

    文章:IHttpModule的那些事 可以自定义类实现IHttpModule接口,然后实现接口方法Init,Init方法可以得到HttpApplication 的实例化对象. 然后给对象的事件的注册各 ...

  10. 关于mybatis的思考(2)——mybatis映射文件的深入理解

    1.配置文件 mybatis进行持久化操作是以SqlSessionFactory对象为基础的,这个对象是整个数据库映射关系经过编译后的内存镜像. InputStream inputStream = R ...