实现ThreadFactory接口生成自定义的线程给Fork/Join框架
Fork/Join框架是Java7中最有趣的特征之一。它是Executor和ExecutorService接口的一个实现,允许你执行Callable和Runnable任务而不用管理这些执行线程。这个执行者面向执行能被拆分成更小部分的任务。主要组件如下:
- 一个特殊任务,实现ForkJoinTask类
- 两种操作,将任务划分成子任务的fork操作和等待这些子任务结束的join操作
- 一个算法,优化池中线程的使用的work-stealing算法。当一个任务正在等待它的子任务(结束)时,它的执行线程将执行其他任务(等待执行的任务)。
ForkJoinPool类是Fork/Join的主要类。在它的内部实现,有如下两种元素:
- 一个存储等待执行任务的列队。
- 一个执行任务的线程池
在这个指南中,你将学习如何实现一个在ForkJoinPool类中使用的自定义的工作者线程,及如何使用一个工厂来使用它。
要自定义ForkJoinPool类使用的线程,必须继承ForkJoinWorkerThread
public class MyWorkerThread extends ForkJoinWorkerThread {
private static ThreadLocal<Integer> taskCounter = new ThreadLocal<Integer>();
protected MyWorkerThread(ForkJoinPool pool) {
super(pool);
}
@Override
protected void onStart() {
super.onStart();
System.out.println("MyWorkerThread " + getId()+ " : Initializing task counter");
taskCounter.set(0);
}
@Override
protected void onTermination(Throwable exception) {
System.out.println("MyWorkerThread " + getId() + " :"
+ taskCounter.get());
super.onTermination(exception);
}
public void addTask() {
int counter = taskCounter.get().intValue();
counter++;
taskCounter.set(counter);
}
}
继承ForkJoinWorkerThreadFactory创建MyWorkerThreadFactory工厂
public class MyWorkerThreadFactory implements ForkJoinWorkerThreadFactory {
@Override
public MyWorkerThread newThread(ForkJoinPool pool) {
return new MyWorkerThread(pool);
}
}
public class MyRecursiveTask extends RecursiveTask<Integer> {
private int array[];
private int start, end;
public MyRecursiveTask(int[] array, int start, int end) {
super();
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
Integer ret;
MyWorkerThread thread = (MyWorkerThread) Thread.currentThread();
thread.addTask();
if (end - start > 100) {
int mid = (start + end) / 2;
MyRecursiveTask task1 = new MyRecursiveTask(array, start, mid);
MyRecursiveTask task2 = new MyRecursiveTask(array, mid, end);
invokeAll(task1, task2);
ret = addResults(task1, task2);
} else {
int add = 0;
for (int i = start; i < end; i++) {
add += array[i];
}
ret = new Integer(add);
}
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
return ret;
}
private Integer addResults(MyRecursiveTask task1, MyRecursiveTask task2) {
int value = 0;
try {
value = task1.get().intValue() + task2.get().intValue();
} catch (Exception e) {
e.printStackTrace();
}
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (Exception e) {
e.printStackTrace();
}
return value;
}
}
public class ForkMain {
public static void main(String[] args) throws Exception {
MyWorkerThreadFactory factory=new MyWorkerThreadFactory();
ForkJoinPool joinPool=new ForkJoinPool(4, factory, null, false);
int array[]=new int[100000];
for (int i =0; i <100000; i++) {
array[i]=i;
}
MyRecursiveTask task=new MyRecursiveTask(array, 0, 10000);
joinPool.execute(task);
task.join();
joinPool.shutdown();
joinPool.awaitTermination(1, TimeUnit.DAYS);
System.out.println("Main: Result:"+task.get());
System.out.println("Main:Ends");
}
}
实现ThreadFactory接口生成自定义的线程给Fork/Join框架的更多相关文章
- 013-多线程-基础-Fork/Join框架、parallelStream讲解
一.概述 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 它同ThreadPoolExecut ...
- java基础|自定义java线程池
线程池创建的参数 在创建线程的各种方式中我们有讲到过通过创建线程池来完成异步操作,但实际上jdk提供的Executors来创建线程池都还有些缺陷,线程池有以下几个参数: 代码节选自源码ThreadPo ...
- 通过用 .NET 生成自定义窗体设计器来定制应用程序
通过用 .NET 生成自定义窗体设计器来定制应用程序 https://www.microsoft.com/china/MSDN/library/netFramework/netframework/Cu ...
- Java Concurrency - ThreadFactory, 使用工厂方法创建线程
当需要创建多个类似的线程实例时,使用工厂模式替代 new 操作符创建线程,能使代码更为简洁,易于维护.JDK 提供了 java.util.concurrent.ThreadFactory 接口,Thr ...
- testng生成自定义html报告
转自:https://blog.csdn.net/kdslkd/article/details/51198433 testng原生的或reportng的报告总有些不符合需要,尝试生成自定义测试报告,用 ...
- 微信公众号第三方平台生成自定义菜单提示 获取"access_token失败"
在微信公众号第三方平台要生成自定义菜单时,程序反应很慢,最终提示"获取access_token失败"(之前程序无改动,使用时间已久),查了大半天,找不出原因. 排除.在微信公众号平 ...
- 参考MongoRepository,为接口生成bean实现注入
首先弄个注解,给代码个入口,这个就是mongo的@EnableMongoRepositories了. @Target(ElementType.TYPE) @Retention(RetentionPol ...
- Mybaits 源码解析 (十一)----- 设计模式精妙使用:静态代理和动态代理结合使用:@MapperScan将Mapper接口生成代理注入到Spring
上一篇文章我们讲了SqlSessionFactoryBean,通过这个FactoryBean创建SqlSessionFactory并注册进Spring容器,这篇文章我们就讲剩下的部分,通过Mapper ...
- 十、自定义ThreadPoolExecutor线程池
自定义ThreadPoolExecutor线程池 自定义线程池需要遵循的规则 [1]线程池大小的设置 1.计算密集型: 顾名思义就是应用需要非常多的CPU计算资源,在多核CPU时代,我们要让每一个CP ...
随机推荐
- Nagios邮件报警
p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-bottom: .0001pt; line-height: 150%; fon ...
- kafka分布式消息队列介绍以及集群安装
简介 首先简单说下对kafka的理解: 1.kafka是一个分布式的消息缓存系统: 2.kafka集群中的服务器节点都被称作broker 3.kafka的客户端分为:一是producer(消息生产者) ...
- Kindle PaperWhite3 越狱和PDF插件的安装
下载所需工具 这里分享的文件是这个教程中所需要的所有文件 所有工具下载链接:http://pan.baidu.com/s/1c249P2S 密码:ozc7 一.准备工作 本越狱方法仅适用于 KO.KV ...
- 腾讯云安全:开发者必看|Android 8.0 新特性及开发指南
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 背景介绍 谷歌2017 I/O开发者大会今年将于5月17-19日在美国加州举办.大会将跟往年一样发布最新的 A ...
- key-value存储Redis
Key-value数据库是一种以键值对存储数据的一种数据库,(类似java中的HashMap)每个键都会对应一个唯一的值. Redis与其他 key - value 数据库相比还有如下特点: Redi ...
- spring之bean
Bean的基本配置 id属性 id属性确定bean的唯一标识符,容器对bean的管理,访问,以及该bean的依赖关系,都通过该属性来完成.bean的id属性在Spring容器中应该是唯一的. clas ...
- gulp基于seaJs模块化项目打包实践【原创】
公司还一直在延续使用jq+seajs的技术栈,所以只能基于现在的技术栈进行静态文件打包,而众所周知seajs的打包比较"偏门",在查了不少的文档和技术分享后终于琢磨出了自己的打包策 ...
- 【2017-04-18】Ado.Net C#连接数据库进行增、删、改、查
一.简介 1.ado.net是一门数据库访问技术. 他可以通过程序来操作数据库 2.类库 Connection 类 和数据库交互,必须连接它.连接帮助指明数据库服务器.数据库名字.用户名.密码,和连接 ...
- Java排序算法之希尔(Shell)排序
基本思想: 希尔排序就是对直接插入排序的一个优化.现在有一个array,希尔排序就是设定一个增量incrementNum(0<incrementNum<array.length).先从ar ...
- seajs加载angularjs
angularjs是自动完成模块的控制的,而seajs加载模块是异步的,所以不做修改,直接seajs加载angularjs会出错. 在这里讲下自己的解决方法 一.需要把ng-ap ...