介绍:

  a . Fork/Join为JKD1.7引入,适用于对大量数据进行拆分成多个小任务进行计算的框架,最后把所有小任务的结果汇总合并得到最终的结果

  b . 相关类

  1. public abstract class RecursiveTask<V> extends ForkJoinTask<V>;
  2. public abstract class RecursiveAction extends ForkJoinTask<Void>;

  c . 其中RecursiveTask在执行有返回值的任务时使用,RecursiveAction在执行没有返回值的任务时使用

实例代码:

  ForkJoin有参无返回值

  参数:map

  1. public class UpdatePlayersTotalTimeTask extends RecursiveAction {
  2.  
  3. private static final int THRESHOLD_NUM = 30;//定义任务的切分阀值
  4. private Map<String,String> players;
  5. private PlayerTotalTimeService playerTotalTimeService;
  6. private MongoDao mongoDao;
  7.  
  8. public UpdatePlayersTotalTimeTask(Map<String,String> players, MongoDao mongoDao) {
  9. this.players = players;
  10. this.mongoDao = mongoDao;
  11. }
  12.  
  13. @Override
  14. protected void compute() {
  15. boolean canCompute = players.size() <= THRESHOLD_NUM;
  16. if (canCompute) {
  17. playerTotalTimeService = new PlayerTotalTimeService();
  18. playerTotalTimeService.updatePlayersTotalTime(players, mongoDao);
  19. } else {
           // 将任务一份为二
  20. int middle = players.size() / 2;
  21.  
  22. int i = 0;
  23. Map<String, String> leftMap = new HashMap<>();
  24. Map<String, String> rightMap = new HashMap<>();
  25.  
  26. for (Map.Entry<String, String> entry : players.entrySet()) {
  27. if (i < middle) {
  28. leftMap.put(entry.getKey(), entry.getValue());
  29. } else {
  30. rightMap.put(entry.getKey(), entry.getValue());
  31. }
  32. i++;
  33. }
  34.  
  35. UpdatePlayersTotalTimeTask leftTask = new UpdatePlayersTotalTimeTask(leftMap, mongoDao);
  36. UpdatePlayersTotalTimeTask rightTask = new UpdatePlayersTotalTimeTask(rightMap, mongoDao);
  37.  
  38. // 执行子任务
  39. leftTask.fork();
  40. rightTask.fork();
  41. }
  42. }

  43.   //调用测试
  44. public static void main(String[] args) throws InterruptedException {
  45. // 创建包含Runtime.getRuntime().availableProcessors()返回值作为个数的并行线程的ForkJoinPool
  46. ForkJoinPool forkjoinPool = new ForkJoinPool();
  47.  
  48. Map<String, String> map = new HashMap<>();
         map.put("key1","value1");
  49. MongoDao mongoDao = new MongoDaoImpl();
  50. //生成一个计算任务
  51. UpdatePlayersTotalTimeTask task = new UpdatePlayersTotalTimeTask(map, mongoDao);
  52. // 提交可分解的PrintTask任务
  53. forkjoinPool.excute(task);
  54. forkjoinPool.awaitTermination(2, TimeUnit.SECONDS);//阻塞当前线程直到 ForkJoinPool 中所有的任务都执行结束
  55. // 关闭线程池
  56. forkjoinPool.shutdown();
  57. }
  58.  
  59. }

  ForkJoin有参有返回值        (继承RecursiveTask<T>类)

  参数:set<String>   返回值:map<String,String>

  1. public class CalcRoomPlayersTotalTimeTask extends RecursiveTask<Map<String,String>> {
  2. private static final int THRESHOLD_NUM = 15;
  3. private Set<String> roomSet;
  4. private PlayerTotalTimeService playerTotalTimeService;
  5. private MongoDao mongoDao;
  6.  
  7. public CalcRoomPlayersTotalTimeTask(Set<String> roomSet, MongoDao mongoDao) {
  8. this.roomSet = roomSet;
  9. this.mongoDao = mongoDao;
  10. }
  11.  
  12. @Override
  13. protected Map<String,String> compute() {
  14.  
  15. playerTotalTimeService = new PlayerTotalTimeService();
  16. //如果任务足够小就计算任务
  17. boolean canCompute = roomSet.size() <= THRESHOLD_NUM;
  18. if (canCompute) {
  19.  
  20. Map<String,String> playersResult = new HashMap<>();
  21.  
  22. playersResult = playerTotalTimeService.calcRoomPlayersTotalTime(roomSet, mongoDao);
  23.  
  24. return playersResult;
  25. } else {
  26. // 如果任务大于阈值,就分裂成两个子任务计算
  27. long middle = roomSet.size() / 2;
  28. Set<String> leftSet = new HashSet<>();
  29. Set<String> rightSet = new HashSet<>();
  30.  
  31. long i = 0;
  32. for (String room : roomSet) {
  33. if (i < middle) {
  34. leftSet.add(room);
  35. } else {
  36. rightSet.add(room);
  37. }
  38. i++;
  39. }
  40.  
  41. CalcRoomPlayersTotalTimeTask leftTask = new CalcRoomPlayersTotalTimeTask(leftSet,mongoDao);
  42. CalcRoomPlayersTotalTimeTask rightTask = new CalcRoomPlayersTotalTimeTask(rightSet,mongoDao);
  43.  
  44. // 执行子任务
  45. invokeAll(leftTask,rightTask);
  46.  
  47. HashMap<String,String> result = new HashMap<>();
  48.  
  49. Map<String,String> leftResult = leftTask.join();
  50. Map<String,String> rightResult = rightTask.join();
  51.  
  52. result.putAll(leftResult);
  53.  
  54. for (Map.Entry<String, String> entry : rightResult.entrySet()) {
  55. boolean contains = result.containsKey(entry.getKey());
  56. if(contains){
  57. String playerTotalTimeStr = entry.getValue();
  58. Long playerTotalTimeLong = playerTotalTimeService.timeStringToLong(result.get(entry.getKey())) + playerTotalTimeService.timeStringToLong(playerTotalTimeStr);
  59. playerTotalTimeStr = playerTotalTimeService.timeLongToString(playerTotalTimeLong);
  60. result.put(entry.getKey(),playerTotalTimeStr);
  61. }else {
  62. result.put(entry.getKey(),entry.getValue());
  63. }
  64. }
  65.  
  66. return result;
  67. }
  68. }
  69.  
  70. public static void main(String[] args) throws InterruptedException {
  71. // 创建包含Runtime.getRuntime().availableProcessors()返回值作为个数的并行线程的ForkJoinPool
  72. ForkJoinPool forkjoinPool = new ForkJoinPool();
  73.  
  74. Set<String> roomSet = new HashSet<>();
  75. Map<String,String> map = new HashMap<String,String>();
  76. MongoDao mongoDao = new MongoDaoImpl();
  77. //生成一个计算任务
  78. CalcRoomPlayersTotalTimeTask task = new CalcRoomPlayersTotalTimeTask(roomSet, mongoDao);
  79.  
  80. // 提交可分解的PrintTask任务
           map = forkjoinPool.invoke(task);
  81. forkjoinPool.awaitTermination(2, TimeUnit.SECONDS);//阻塞当前线程直到 ForkJoinPool 中所有的任务都执行结束
  82. // 关闭线程池
  83. forkjoinPool.shutdown();
  84. }
  85. }

说明:

  a .在有大量计算任务时,此框架方法可进行并行计算效率高,以上示例,可以根据具体的业务需求更改属性及相关方法用于匹配自己的业务逻辑

b .JDK1.8后由于加入Stream流的操作,集合框架可以使用Collection<E> default Stream<E> parallelStream()的方法转换成并行流进行计算,此时效果与Fork/Join任务同效

c .ForkJoinPool中的多种方法

  1. public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task);//等待获取结果
  2. public void execute(ForkJoinTask<?> task);//异步执行
  3. public <T> T invoke(ForkJoinTask<T> task);//执行,获取Future

d .ForkJoinTask在执行的时候可能会抛出异常,但是没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常。getException方             法返回Throwable对象,如果任务被取消了则返回CancellationException。如果任务没有完成或者没有抛出异常则返回null。

  1. if(task.isCompletedAbnormally()) {
  2. System.out.println(task.getException());
  3. }

注:部分内容引自https://segmentfault.com/a/1190000010209196

ForkJoin有参无返回值、有参有返回值实例的更多相关文章

  1. 慕课网-Java入门第一季-7-2 Java 中无参无返回值方法的使用

    来源:http://www.imooc.com/code/1578 如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法. 方法的使用分两步: 第一步,定义方法 例如:下面代码定义了一个方法名 ...

  2. Java 中无参无返回值方法的使用

    如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法. 方法的使用分两步: 第一步,定义方法 例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 “ ...

  3. 065 01 Android 零基础入门 01 Java基础语法 08 Java方法 02 带参无返回值方法

    065 01 Android 零基础入门 01 Java基础语法 08 Java方法 03 带参无返回值方法 本文知识点:带参无返回值方法 说明:因为时间紧张,本人写博客过程中只是对知识点的关键步骤进 ...

  4. 063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法

    063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法 本文知识点:无参无返回值方法 无参无返回值方法 案例 为什么使用方法?--方便复杂问题调用 ...

  5. 超全table功能Datatables使用的填坑之旅--2:post 动态传参: 解决: ajax 传参无值问题.

    官网解释与方法:1 当向服务器发出一个ajax请求,Datatables将会把服务器请求到的数据构造成一个数据对象. 2 实际上他是参考jQuery的ajax.data属性来的,他能添加额外的参数传给 ...

  6. Java JDBC调用存储过程:无参、输入带参、输出及输出带参

    Java JDBC调用存储过程:无参.输入带参.输出及输出带参 示例代码: package xzg; import java.sql.CallableStatement; import java.sq ...

  7. python中的无参装饰器和有参装饰器

    python中的无参装饰器和有参装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 装饰器特点: 1>.开放封闭原则,即对扩展是开放的,对修改时封闭的: 2>.装饰器 ...

  8. C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解  ...

  9. WebApi接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...

随机推荐

  1. js提交数据时需判断是点击事件还是回车键

    使用回车键实质还是点击事件==回车时将焦点聚居在某个标签上. Html代码: <div id="btlogin" class="btlogin">& ...

  2. linux命令-vim一般模式下复制剪切粘贴

    删除光标后的一个字符 x 删除光标前的一个字符 shift+x 删除指定个数的字符 数字+x 删除一行字符 dd 剪切指定行数  数字dd  3dd 剪切3行 其实并没有删掉而是保存着剪切板里 粘贴在 ...

  3. jquery.html5uploader.js 上传控件

    插件地址:http://blog.csdn.net/never_say_goodbye/article/details/8598521 先上个效果图: 相比来说,效果还是很不错的 使用MVC3做服务器 ...

  4. python fabric的安装与使用

    背景:fabric主要执行远程的shell命令,包括文件的上传.下载,以及提示用户输入等辅助其它功能. 测试系统:ubuntu16 要求:python //系统有自带,ubuntu16 通常自带pyt ...

  5. shell自动收集服务器硬件系统信息

    shell自动收集服务器硬件系统信息,插入数据库并通过web页面显示. 一,shell自动收集服务器硬件系统信息,插入数据库.#centos 7操作系统下 #!/bin/bash #auto get ...

  6. 【总结整理】overflow: auto/hidden;清除自己

    .top-nav{ font-size: 12px; font-weight: bold; list-style-type: none; border-bottom: 8px solid #DC4E1 ...

  7. vue 报错 Uncaught (in promise) error

    可尝试在then()后加上catch() ps:该图来自网络

  8. Dreamweaver Flash Photoshop网页设计综合应用 (智云科技) [iso] 1.86G

    全书共15章,主要包括网页制作基础.Dreamweaver CC网页制作.Photoshop CC网页图像设计.Flash CC网页动画设计以及综合案例实战5个部分.通过本书的学习,不仅能让读者学会三 ...

  9. Tensorflow函数——tf.placeholder()函数

    tf.placeholder()函数 Tensorflow中的palceholder,中文翻译为占位符,什么意思呢? 在Tensoflow2.0以前,还是静态图的设计思想,整个设计理念是计算流图,在编 ...

  10. React 从入门到进阶之路(三)

    之前的文章我们介绍了 React 创建组件.JSX 语法.绑定数据和绑定对象.接下来我们将介绍 React 绑定属性( 绑定class  绑定style).引入图片  循环数组渲染数据. 上一篇中我们 ...