Java并发编程--Fork/Join框架使用
上篇博客我们介绍了通过CyclicBarrier使线程同步,可是上述方法存在一个问题,那就是假设一个大任务跑了2个线程去完毕。假设线程2耗时比线程1多2倍。线程1完毕后必须等待线程2完毕。等待的过程线程1没法复用。如今我们准备解决问题,我们希望线程1完毕自己的任务后能去帮助线程2完毕一部分任务。
Java7引如了Fork/Join框架能够非常好的解决问题。
Fork/Join是一个用于并行运行任务的框架,是一个把大任务切割成若干个小任务。最后汇总每一个小任务结果后得到大任务结果的框架。
fork是分叉。join是结合。
以下看张图来清晰的认识一下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQva2FuZ2xpeDFhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
事实上Fork/Join本质上是分治算法的一种实现。以下我们来看怎么详细使用:
ForkJoinTask:我们要使用Fork/Join框架,必须首先创建一个Fork/Join任务。它提供在任务中运行fork()和join()操作的机制,通常情况下我们不须要直接继承ForkJoinTask类。而仅仅须要继承它的子类,Fork/Join框架提供了下面两个子类:
RecursiveAction:用于没有返回结果的任务。
RecursiveTask :用于有返回结果的任务。
ForkJoinPool:ForkJoinTask须要通过ForkJoinPool来运行,任务切割出的子任务会加入到当前工作线程所维护的双端队列中,进入队列的头部。
当一个工作线程的队列里临时没有任务时,它会随机从其它工作线程的队列的尾部获取一个任务。
以下,我们相同实现考试系统抽题的样例。
public class GetQuestionsTask extends RecursiveTask<List> {
//參数map
private Map map;
//參数list==仅仅放题型
private List questionTypeList;
public GetQuestionsTask(List questionTypeList,Map map) {
this.questionTypeList = questionTypeList;
this.map=map;
}
@Override
protected List compute() {
System.out.println(questionTypeList.size());
List list = new ArrayList();
if (questionTypeList.size() < 2) {
// 抽题
list = getQuestions(questionTypeList,map);
} else {
int size = questionTypeList.size();
int mid = size / 2;
GetQuestionsTask task1 = new GetQuestionsTask(
questionTypeList.subList(0, mid),map);
GetQuestionsTask task2 = new GetQuestionsTask(
questionTypeList.subList(mid, size),map);
invokeAll(task1, task2);
try {
list = groupResults(task1.get(), task2.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return list;
}
//合并抽题结果
private List groupResults(List list1, List list2) {
System.out.println(Thread.currentThread().getName()+"開始合并结果......");
// 合并返回结果
List list = new ArrayList();
list.addAll(list1);
list.addAll(list2);
System.out.println(Thread.currentThread().getName()+"合并结果结束......");
return list;
}
// 抽题
private List getQuestions(List questTypeList,Map map) {
List list = new ArrayList();
for(int i=0;i<questTypeList.size();i++){
System.out.println(Thread.currentThread().getName()+"開始抽题......"+questionTypeList.get(i).toString());
//假数据,向list中放试题
list.add("0");
list.add("1");
list.add("2");
list.add("3");
list.add("4");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"抽题结束..."+questionTypeList.get(i).toString());
}
return list;
}
}
client:
//该池的线程数量不会超过0*7fff个(32767)
//池中维护着ForkJoinWorkerThread对象数组,数组大小由parallelism属性决定,parallelism默觉得处理器个数
ForkJoinPool pool = new ForkJoinPool();
GetQuestionsTask task = new GetQuestionsTask(questionTypeList, map);
pool.execute(task);
// 试题列表=task.get()
try {
List finalList = task.get();
System.out.println("终于结果个数:" + finalList.size());
} catch (InterruptedException e) { e.printStackTrace();
} catch (ExecutionException e) { e.printStackTrace();
}
总结:
Fork/Join实现了“工作窃取算法”,当一个工作线程的队列里临时没有任务时。它会随机从其它工作线程的队列的尾部获取一个任务。当然,fork/join框架的使用有一定的约束条件:
1.除了fork() 和 join()方法外,线程不得使用其它的同步工具。
线程最好也不要sleep()
2.线程不得进行I/O操作
3.线程不得抛出checked exception。
Java并发编程--Fork/Join框架使用的更多相关文章
- Java 并发编程 -- Fork/Join 框架
概述 Fork/Join 框架是 Java7 提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架.下图是网上流传的 Fork Join 的 ...
- 【fork/join】java并发编程-fork/join示例
package com.chinamobile.epic.tako.common.graphite.query.sync.impl; import com.google.common.collect. ...
- java 中的fork join框架
文章目录 ForkJoinPool ForkJoinWorkerThread ForkJoinTask 在ForkJoinPool中提交Task java 中的fork join框架 fork joi ...
- Java 并发之 Fork/Join 框架
什么是 Fork/Join 框架 Fork/Join 框架是一种在 JDk 7 引入的线程池,用于并行执行把一个大任务拆成多个小任务并行执行,最终汇总每个小任务结果得到大任务结果的特殊任务.通过其命名 ...
- JAVA中的Fork/Join框架
看了下Java Tutorials中的fork/join章节,整理下. 什么是fork/join框架 fork/join框架是ExecutorService接口的一个实现,可以帮助开发人员充分利用多核 ...
- Java并发编程之——Amino框架
Amino框架是一个采用无锁方式实现并行计算的框架,可惜的是,网上关于Amino框架的介绍甚少.根据所掌握的资料,稍微总结一下: 1. 锁机制到无锁机制 锁机制可以确保程序和数据的线程安全,但是锁是一 ...
- Java并发编程--4.Executor框架
简介 Executor框架是启动,管理线程的API, 它的内部实现是线程池机制,它有很多好处,比如使任务提交和任务执行解耦合,防止this逃逸:它的主要API包括: Executor, Execut ...
- Java并发编程(08):Executor线程池框架
本文源码:GitHub·点这里 || GitEE·点这里 一.Executor框架简介 1.基础简介 Executor系统中,将线程任务提交和任务执行进行了解耦的设计,Executor有各种功能强大的 ...
- JAVA并发编程J.U.C学习总结
前言 学习了一段时间J.U.C,打算做个小结,个人感觉总结还是非常重要,要不然总感觉知识点零零散散的. 有错误也欢迎指正,大家共同进步: 另外,转载请注明链接,写篇文章不容易啊,http://www. ...
随机推荐
- java模拟实现生产者---消费者问题
本文章为小编原创,请尊重文章的原创性,转载请注意写明转载来源:http://blog.csdn.net/u012116457 已知技术參数: 生产者消费者问题,描写叙述一组生产者向一组消费者提供产品/ ...
- 数据交换工具Kettle
网上搜集了一些关于开源数据交换工具Kattle的文章,特收藏例如以下: 文章一:ETL和Kettle简单介绍 ETL即数据抽取(Extract).转换(Transform).装载(Load)的过程.它 ...
- GCC 编译使用动态链接库和静态链接库的方法
1 库的分类 依据链接时期的不同,库又有静态库和动态库之分. 静态库是在链接阶段被链接的.所以生成的可执行文件就不受库的影响了.即使库被删除了,程序依旧能够成功执行. 有别于静态库,动态库的链接是在程 ...
- [VBS]_[活动分组程序]
场景: 1.每次搞活动都需要分组,比如20个人分3个组,如何才能更公平的分组,想到的只能是随机分组程序. 2.时间关系并没有实现男女平衡的分组,有时间的哥们可以自己实现. 文件1:分组程序.vbs,记 ...
- C++ 中使用boost::property_tree读取解析ini文件
boost 官网 http://www.boost.org/ 下载页面 http://sourceforge.net/projects/boost/files/boost/1.53.0/ 我下载的是 ...
- graph driver-device mapper-04libdevmapper基本操作
// 创建thin pool // 调用路径:NewDeviceSet->initDevmapper->createPool 1.1 func createPool(poolName st ...
- Winfrom设置DataGridView单元格获得焦点(DataGridView - CurrentCell)
设置DataGridView单元格获得焦点 this.dgv_prescription.BeginEdit(true);
- 使用gradle打包jar包
近期用android studio来做android开发的IDE,它是使用gradle来构建的,于是開始学习gradle. 如今有一个项目,里面有一个android-library的模块.我想在做re ...
- Java 实现观察者(Observer)模式
1. Java自带的实现 类图 /** * 观察目标 继承自 java.util.Observable * @author stone * */ public class UpdateObservab ...
- Filter和FilterChain具体的使用说明
一.Filter的介绍及使用 什么是过滤器? 与Servlet类似,过滤器是一些web应用程序组件,能够绑定到一个web应用程序中.可是与其它web应用程序组件不同的是,过滤器是"链&quo ...