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的园友们速速动起来,跟着博主一起来学习吧.作为程序猿,我们都知道参数和返回值是编程领域不可分割的两大块,此前分享了 ...
随机推荐
- window下rails4.1 发生TZInfo::DataSourceNotFound 错误 - smallbottle
在官网上学习rails 4.1 ,启动rails server之后发生了如下错误 $ rails server Booting WEBrick Rails 4.1.0 application star ...
- CentOS7 搭建LNMP
一. 安装依赖文件 1. sudo yum install gcc gcc-c++ zlib zlib-devel libxml2 libxml2-devel openssl open ...
- 关于android中两种service的编写简单总结
1.startservice (两种方法,继承service类或者继承intentservice 类) 继承service类,在onstartcommend重载方法中实现业务逻辑的处理,如果耗时过长最 ...
- [51nod1116]K进制下的大数
解题关键:$A\% (k - 1) = (A[0] + A[1]*k + A[2]*{k^2} + ...A[n]*{k^n})\% (k - 1) = (A[0] + A[1] + ...A[n]) ...
- Luogu 4868 Preprefix sum
类似于树状数组维护区间的方法. 每一次询问要求$\sum_{i = 1}^{n}\sum_{j = 1}^{i}a_j$. 展开一下: $\sum_{i = 1}^{n}\sum_{j = 1}^{i ...
- adb devices unauthorized解决方法
有时候使用adb连接手机时,即使打开了usb调试,手机添加了信任,仍然出现unauthorized的提示 解决办法如下: 先上两张stack overflow上面的图片: 很多人可能看不懂.翻一下大概 ...
- 20. CTF综合靶机渗透(十三)
靶机说明: Wellcome to "PwnLab: init", my first Boot2Root virtual machine. Meant to be easy, I ...
- java8 创建树结构的数据
private List<TreeNode> createTree(Integer pid, Map<Integer, List<SysPermission>> m ...
- Library学习日志(……)
添加Library在buildpath中,就是右键工程->properties->java buildpath->Libraries 然后点击add Library就是添加Libra ...
- 基础篇---memcache
十分钟学会memcache,比你想象的要简单 转发:https://baijiahao.baidu.com/s?id=1588816843517136163&wfr=spider&fo ...