ForkJoin有参无返回值、有参有返回值实例
介绍:
a . Fork/Join为JKD1.7引入,适用于对大量数据进行拆分成多个小任务进行计算的框架,最后把所有小任务的结果汇总合并得到最终的结果
b . 相关类
public abstract class RecursiveTask<V> extends ForkJoinTask<V>;
public abstract class RecursiveAction extends ForkJoinTask<Void>;
c . 其中RecursiveTask在执行有返回值的任务时使用,RecursiveAction在执行没有返回值的任务时使用
实例代码:
ForkJoin有参无返回值
参数:map
public class UpdatePlayersTotalTimeTask extends RecursiveAction {
private static final int THRESHOLD_NUM = 30;//定义任务的切分阀值
private Map<String,String> players;
private PlayerTotalTimeService playerTotalTimeService;
private MongoDao mongoDao;
public UpdatePlayersTotalTimeTask(Map<String,String> players, MongoDao mongoDao) {
this.players = players;
this.mongoDao = mongoDao;
}
@Override
protected void compute() {
boolean canCompute = players.size() <= THRESHOLD_NUM;
if (canCompute) {
playerTotalTimeService = new PlayerTotalTimeService();
playerTotalTimeService.updatePlayersTotalTime(players, mongoDao);
} else {
// 将任务一份为二
int middle = players.size() / 2;
int i = 0;
Map<String, String> leftMap = new HashMap<>();
Map<String, String> rightMap = new HashMap<>();
for (Map.Entry<String, String> entry : players.entrySet()) {
if (i < middle) {
leftMap.put(entry.getKey(), entry.getValue());
} else {
rightMap.put(entry.getKey(), entry.getValue());
}
i++;
}
UpdatePlayersTotalTimeTask leftTask = new UpdatePlayersTotalTimeTask(leftMap, mongoDao);
UpdatePlayersTotalTimeTask rightTask = new UpdatePlayersTotalTimeTask(rightMap, mongoDao);
// 执行子任务
leftTask.fork();
rightTask.fork();
}
}
//调用测试
public static void main(String[] args) throws InterruptedException {
// 创建包含Runtime.getRuntime().availableProcessors()返回值作为个数的并行线程的ForkJoinPool
ForkJoinPool forkjoinPool = new ForkJoinPool();
Map<String, String> map = new HashMap<>();
map.put("key1","value1");
MongoDao mongoDao = new MongoDaoImpl();
//生成一个计算任务
UpdatePlayersTotalTimeTask task = new UpdatePlayersTotalTimeTask(map, mongoDao);
// 提交可分解的PrintTask任务
forkjoinPool.excute(task);
forkjoinPool.awaitTermination(2, TimeUnit.SECONDS);//阻塞当前线程直到 ForkJoinPool 中所有的任务都执行结束
// 关闭线程池
forkjoinPool.shutdown();
}
}
ForkJoin有参有返回值 (继承RecursiveTask<T>类)
参数:set<String> 返回值:map<String,String>
public class CalcRoomPlayersTotalTimeTask extends RecursiveTask<Map<String,String>> {
private static final int THRESHOLD_NUM = 15;
private Set<String> roomSet;
private PlayerTotalTimeService playerTotalTimeService;
private MongoDao mongoDao;
public CalcRoomPlayersTotalTimeTask(Set<String> roomSet, MongoDao mongoDao) {
this.roomSet = roomSet;
this.mongoDao = mongoDao;
}
@Override
protected Map<String,String> compute() {
playerTotalTimeService = new PlayerTotalTimeService();
//如果任务足够小就计算任务
boolean canCompute = roomSet.size() <= THRESHOLD_NUM;
if (canCompute) {
Map<String,String> playersResult = new HashMap<>();
playersResult = playerTotalTimeService.calcRoomPlayersTotalTime(roomSet, mongoDao);
return playersResult;
} else {
// 如果任务大于阈值,就分裂成两个子任务计算
long middle = roomSet.size() / 2;
Set<String> leftSet = new HashSet<>();
Set<String> rightSet = new HashSet<>();
long i = 0;
for (String room : roomSet) {
if (i < middle) {
leftSet.add(room);
} else {
rightSet.add(room);
}
i++;
}
CalcRoomPlayersTotalTimeTask leftTask = new CalcRoomPlayersTotalTimeTask(leftSet,mongoDao);
CalcRoomPlayersTotalTimeTask rightTask = new CalcRoomPlayersTotalTimeTask(rightSet,mongoDao);
// 执行子任务
invokeAll(leftTask,rightTask);
HashMap<String,String> result = new HashMap<>();
Map<String,String> leftResult = leftTask.join();
Map<String,String> rightResult = rightTask.join();
result.putAll(leftResult);
for (Map.Entry<String, String> entry : rightResult.entrySet()) {
boolean contains = result.containsKey(entry.getKey());
if(contains){
String playerTotalTimeStr = entry.getValue();
Long playerTotalTimeLong = playerTotalTimeService.timeStringToLong(result.get(entry.getKey())) + playerTotalTimeService.timeStringToLong(playerTotalTimeStr);
playerTotalTimeStr = playerTotalTimeService.timeLongToString(playerTotalTimeLong);
result.put(entry.getKey(),playerTotalTimeStr);
}else {
result.put(entry.getKey(),entry.getValue());
}
}
return result;
}
}
public static void main(String[] args) throws InterruptedException {
// 创建包含Runtime.getRuntime().availableProcessors()返回值作为个数的并行线程的ForkJoinPool
ForkJoinPool forkjoinPool = new ForkJoinPool();
Set<String> roomSet = new HashSet<>();
Map<String,String> map = new HashMap<String,String>();
MongoDao mongoDao = new MongoDaoImpl();
//生成一个计算任务
CalcRoomPlayersTotalTimeTask task = new CalcRoomPlayersTotalTimeTask(roomSet, mongoDao);
// 提交可分解的PrintTask任务
map = forkjoinPool.invoke(task);
forkjoinPool.awaitTermination(2, TimeUnit.SECONDS);//阻塞当前线程直到 ForkJoinPool 中所有的任务都执行结束
// 关闭线程池
forkjoinPool.shutdown();
}
}
说明:
a .在有大量计算任务时,此框架方法可进行并行计算效率高,以上示例,可以根据具体的业务需求更改属性及相关方法用于匹配自己的业务逻辑
b .JDK1.8后由于加入Stream流的操作,集合框架可以使用Collection<E> default Stream<E> parallelStream()的方法转换成并行流进行计算,此时效果与Fork/Join任务同效
c .ForkJoinPool中的多种方法
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task);//等待获取结果
public void execute(ForkJoinTask<?> task);//异步执行
public <T> T invoke(ForkJoinTask<T> task);//执行,获取Future
d .ForkJoinTask在执行的时候可能会抛出异常,但是没办法在主线程里直接捕获异常,所以ForkJoinTask提供了isCompletedAbnormally()方法来检查任务是否已经抛出异常或已经被取消了,并且可以通过ForkJoinTask的getException方法获取异常。getException方 法返回Throwable对象,如果任务被取消了则返回CancellationException。如果任务没有完成或者没有抛出异常则返回null。
if(task.isCompletedAbnormally()) {
System.out.println(task.getException());
}
注:部分内容引自https://segmentfault.com/a/1190000010209196
ForkJoin有参无返回值、有参有返回值实例的更多相关文章
- 慕课网-Java入门第一季-7-2 Java 中无参无返回值方法的使用
来源:http://www.imooc.com/code/1578 如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法. 方法的使用分两步: 第一步,定义方法 例如:下面代码定义了一个方法名 ...
- Java 中无参无返回值方法的使用
如果方法不包含参数,且没有返回值,我们称为无参无返回值的方法. 方法的使用分两步: 第一步,定义方法 例如:下面代码定义了一个方法名为 show ,没有参数,且没有返回值的方法,执行的操作为输出 “ ...
- 065 01 Android 零基础入门 01 Java基础语法 08 Java方法 02 带参无返回值方法
065 01 Android 零基础入门 01 Java基础语法 08 Java方法 03 带参无返回值方法 本文知识点:带参无返回值方法 说明:因为时间紧张,本人写博客过程中只是对知识点的关键步骤进 ...
- 063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法
063 01 Android 零基础入门 01 Java基础语法 08 Java方法 01 无参无返回值方法 本文知识点:无参无返回值方法 无参无返回值方法 案例 为什么使用方法?--方便复杂问题调用 ...
- 超全table功能Datatables使用的填坑之旅--2:post 动态传参: 解决: ajax 传参无值问题.
官网解释与方法:1 当向服务器发出一个ajax请求,Datatables将会把服务器请求到的数据构造成一个数据对象. 2 实际上他是参考jQuery的ajax.data属性来的,他能添加额外的参数传给 ...
- Java JDBC调用存储过程:无参、输入带参、输出及输出带参
Java JDBC调用存储过程:无参.输入带参.输出及输出带参 示例代码: package xzg; import java.sql.CallableStatement; import java.sq ...
- python中的无参装饰器和有参装饰器
python中的无参装饰器和有参装饰器 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 装饰器特点: 1>.开放封闭原则,即对扩展是开放的,对修改时封闭的: 2>.装饰器 ...
- C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解
前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解 ...
- WebApi接口返回值不困惑:返回值类型详解
前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...
随机推荐
- 关于KMeans 最外围点移除实验(其中心保持不变)
import matplotlib.pyplot as plt from sklearn.datasets import make_blobs import numpy as np X,labels ...
- Android源码中添加APP
参考罗升阳<Android系统源代码情景分析> 在Android源码中,我们通常把实验性质的Android APP放在packages/experimental目录下.对于一个简单的应用程 ...
- CSDN优秀博客连接,博客之星连接。
点击链接 获得[红杏出墙]插件,FQ上网无压力!谷歌搜索无压力! 2013年度CSDN十大博客之星 TOP 作者 专注领域 博客地址 邹晓艺 机器学习及算法 zouxy09 2 王然 潜在的集大成者 ...
- shell脚本备份系统的方法
linux自动备份shell(使用全备份,增量备份策略) 在cron里设置,每周日晚12点执行(每周日全备份,其余时间增量备份)#vi backup.sh #!/bin/bash # definewe ...
- p2345 奶牛集会
传送门 题目 约翰的N 头奶牛每年都会参加“哞哞大会”.哞哞大会是奶牛界的盛事.集会上的活动很 多,比如堆干草,跨栅栏,摸牛仔的屁股等等.它们参加活动时会聚在一起,第i 头奶牛的坐标为Xi,没有两头奶 ...
- hdu1085
#include <iostream> #include <cstring> using namespace std; int n[3],a[9000],b[9000],i,j ...
- C#交换两个数字
- 微信小程地图片未加载成功的情况 Failed to load local image resource
在开发小程序的时候,发现在加载图片时并没有异常,但是后台却报错了. 例如以下我的一段代码: <view class="useage2 "> <image src= ...
- Loadrunner监控服务器资源
LoadRunner 加载监听服务器的步骤如下: 1.在 LoadRunner Controller 下,将工作面板切换到 Run状态,Available Graphs 栏 ,System Resou ...
- C#面向对象三大特性之二:继承
面向对象的三大特性之一的封装,解决了将对同一对象所能操作的所有信息放在一起,实现统一对外调用,实现了同一对象的复用,降低了耦合. 但在实际应用中,有好多对象具有相同或者相似的属性,比如有一个对象 果树 ...