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的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...
随机推荐
- 面向对象(Java中普通代码块,构造代码块,静态代码块区别及代码示例)
//执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 //普通代码块:在 ...
- 5.JasperReports学习笔记5-其它数据生成动态的报表(WEB)
转自:http://www.blogjava.net/vjame/archive/2013/10/12/404908.html 一.空数据(Empty Datasources) 就是说JRXML文件里 ...
- kvm基础 虚拟机内存、CPU调整
转自http://blog.csdn.net/hnhuangyiyang/article/details/50902223 一.调小虚拟机内存 调小虚拟机内存可以动态实现,不用关机1.查看当前内存大小 ...
- HTML5小知识
1.HTML5一种“妥协的”语法 2.特点: 标签不区分大小写 元素可以省略结束标签 元素属性可以省略属性值 属性的属性值可以不适用引号
- UI面试题(1)
1.请创建一个数组对象[@“ad”,@“bc”,@“sdf”,@“yu”],并且对该数组对象进行排序(使用冒泡排序); NSMutableArray *array = [NSMutableArraya ...
- 树莓派 Learning 002 必备的操作 --- 08 实现PC端 远程登入 树莓派 --- 法1 远程登入树莓派的命令行状态
树莓派 必备的操作 - 实现PC端 远程登入 树莓派 - 法1 远程登入树莓派的命令行状态 我的树莓派型号:Raspberry Pi 2 Model B V1.1 装机系统:NOOBS v1.9.2 ...
- cygwin运行git submodule init出错error while loading shared libraries的解决
installing the Devel\gettext package should solve your problem. git-submodule requires that. Unfortu ...
- Entity Framework Code-First(13):Configure Many-to-Many
Configure Many-to-Many relationship: Here, we will learn how to configure Many-to-Many relationship ...
- 9. CTF综合靶机渗透(二)
靶机说明 Welcome to the world of Acid. Fairy tails uses secret keys to open the magical doors. 欢迎来到酸的世界. ...
- 网页游戏开发秘笈 PDF扫描版
精选10种常见的游戏类型,透过典型实例,深入剖析游戏引擎及工具的选用技巧,详细讲解每款游戏的制作过程,为快速掌握网页游戏开发提供系统而实用的指南. 网页游戏开发秘笈 目录: 译者序 前 言 导 言 ...