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的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...
随机推荐
- MVC4.0 里的分析器错误
这种错误有很多,今天碰到了,代码段写在if里就回出错,应该是认冲了吧 @if (Web.Common.UserInfo.CurrentUserInfo != null) ...
- ng2 样式控制之style绑定和class绑定
- python unittest之断言及示例
python unintest单元测试框架提供了一整套内置的断言方法. 如果断言失败,则抛出一个AssertionError,并标识该测试为失败状态 如果异常,则当做错误来处理 注意:以上两种方式的区 ...
- mysql auto reset
参数说明: •相关参数说明: •dataSource: 要连接的 datasource (通常我们不会定义在 server.xml) defaultAutoCommit: 对于事务是否 autoCom ...
- js中的Number方法
1.Number.toExponential(fractionDigits) 把number转换成一个指数形式的字符串.可选参数控制其小数点后的数字位数.它必须在0~20之间. 例如: documen ...
- CSS 布局_如何实现容器中每一行的子容器数量随着浏览器宽度的变化而变化?
实现一个浮动布局,红色容器中每一行的蓝色容器数量随着浏览器宽度的变化而变化,就如下图: 要实现这样一个布局,我们首先需要如下的 HTML: <div id="float-contain ...
- CodeForces 489D Unbearable Controversy of Being (不知咋分类 思维题吧)
D. Unbearable Controversy of Being time limit per test 1 second memory limit per test 256 megabytes ...
- IDEA拷贝git上的最新项目资源
File->new ->project version control->git-> 进入项目git对应的网址,选择第一个backstop,复制url: 输入git用户名和密码 ...
- HDU 5236 Article (概率DP+贪心)
题意:要求输入一篇N个字符的文章,对所有非负整数i:每到第i+0.1秒时可以输入一个文章字符,每到第i+0.9秒时有P的概率崩溃(回到开头或者上一个存盘点) 每到第i秒有一次机会可以选择按下X个键存盘 ...
- xilinx planahead partial reconfiguration
1.为什么要使用reconfiguration? reconfiguration,即逻辑可重配,指的是FPGA的逻辑只加载指定区域(功能)的逻辑,而对除此之外的逻辑不产生影响,最常用的就是PCIe/P ...