实现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 ...
随机推荐
- 老李分享:DBA
poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.如果对课程感兴趣,请大家咨询qq:908821478,咨询电话010-845052 ...
- 接口测试培训:HTTP协议基础
接口测试培训:HTTP协议基础 引言 HTTP是一个属于应用层的面向对象的协议,由于其简捷.快速的方式,适用于分布式超媒体信息系统.它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展. ...
- laravel redis Error while reading line from the server.
代码运行一段时间后,会报下面的错误. [Predis\Connection\ConnectionException] Error while reading line from the server. ...
- 项目在App Store的展示信息
一.首部1.图标作用:一个软件的logo.修改:每次提交新版本时可以修改.要求:1>1024*1024像素 2>72dpi.RGB.平展.不透明.没有圆角 3>高品质的JPEG或PN ...
- MySQL学习笔记(二)—查询
一.多表连接查询 新建两张表t_user.t_order. 1.内连接 返回满足条件的所有记录. (1)显式内连接 使用inner join关键字,在on ...
- require.js学习笔记
使用require.js的好处? 1 有效的防止命名冲突(可以将变量封装在模块内,通过暴露出的接口解决命名冲突) 2 解决不同JS文件中的依赖 3 可以让我们的代码以模块化的方式组织 官方网站http ...
- Divide Groups(分组)
题目链接 题目大意是说输入数字n 然后告诉你第i个人都认识谁? 让你把这些人分成两堆,使这每个堆里的人都互相认识. 做法:把不是互相认识的人建立一条边,则构建二分图,两堆的人肯定都互相认识,也就是说, ...
- 在eclipse中使用Maven建web工程项目
在eclipse中使用Maven建web工程项目: 第一种方式: 右键新建maven工程,勾选创建一个简单工程 填入信息,注意打包方式要改为war 点击完成,创建完的工程目录如下: 项目中没有WEB- ...
- redis 压缩链表
redis 压缩链表 概述 压缩链表是相对于普通链表而言的 当普通链表的数据越来越多, 链表查询性能会低效 当存储的数据较少时, 使用链表存储会浪费空间 压缩链表本质上是一个字符串 压缩链表内存储的数 ...
- java复习(9)---数据库JDBC
java写工程当然需要连接数据库.JDBC技术是连接数据库和应用程序的纽带,本节主要说明如何连接数据库. java中提供sql类. package re09; import java.sql.*; p ...