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框架的更多相关文章

  1. 013-多线程-基础-Fork/Join框架、parallelStream讲解

    一.概述 Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 它同ThreadPoolExecut ...

  2. java基础|自定义java线程池

    线程池创建的参数 在创建线程的各种方式中我们有讲到过通过创建线程池来完成异步操作,但实际上jdk提供的Executors来创建线程池都还有些缺陷,线程池有以下几个参数: 代码节选自源码ThreadPo ...

  3. 通过用 .NET 生成自定义窗体设计器来定制应用程序

    通过用 .NET 生成自定义窗体设计器来定制应用程序 https://www.microsoft.com/china/MSDN/library/netFramework/netframework/Cu ...

  4. Java Concurrency - ThreadFactory, 使用工厂方法创建线程

    当需要创建多个类似的线程实例时,使用工厂模式替代 new 操作符创建线程,能使代码更为简洁,易于维护.JDK 提供了 java.util.concurrent.ThreadFactory 接口,Thr ...

  5. testng生成自定义html报告

    转自:https://blog.csdn.net/kdslkd/article/details/51198433 testng原生的或reportng的报告总有些不符合需要,尝试生成自定义测试报告,用 ...

  6. 微信公众号第三方平台生成自定义菜单提示 获取"access_token失败"

    在微信公众号第三方平台要生成自定义菜单时,程序反应很慢,最终提示"获取access_token失败"(之前程序无改动,使用时间已久),查了大半天,找不出原因. 排除.在微信公众号平 ...

  7. 参考MongoRepository,为接口生成bean实现注入

    首先弄个注解,给代码个入口,这个就是mongo的@EnableMongoRepositories了. @Target(ElementType.TYPE) @Retention(RetentionPol ...

  8. Mybaits 源码解析 (十一)----- 设计模式精妙使用:静态代理和动态代理结合使用:@MapperScan将Mapper接口生成代理注入到Spring

    上一篇文章我们讲了SqlSessionFactoryBean,通过这个FactoryBean创建SqlSessionFactory并注册进Spring容器,这篇文章我们就讲剩下的部分,通过Mapper ...

  9. 十、自定义ThreadPoolExecutor线程池

    自定义ThreadPoolExecutor线程池 自定义线程池需要遵循的规则 [1]线程池大小的设置 1.计算密集型: 顾名思义就是应用需要非常多的CPU计算资源,在多核CPU时代,我们要让每一个CP ...

随机推荐

  1. 记一次解析XML转对象的笔记

    项目中调用第三方API,返回格式是XML字符串,需要将XML反序列化为对象,格式如下: <?xml version="1.0"?> <Response xmlns ...

  2. 关于JavaScript中连等赋值那点事

    今天看了前端网上关于JS的题目,其中有一道题目挺有意思的.如下 var a = b =10; (function(){ var a = b = 20; })(); console.log(a); co ...

  3. 一键部署Kubernetes高可用集群

    三台master,四台node,系统版本为CentOS7 IP ROLE 172.60.0.226 master01 172.60.0.86 master02 172.60.0.106 master0 ...

  4. css grid布局的首次使用

    首先来看一下效果图 接下来废话不多说,先上代码 <!DOCTYPE html> <html lang="en"> <head> <meta ...

  5. Android -- onMeasure()源码分析

    1,作为自定义控件最重要的三个方法之一,onMeasure()可以说是我们研究的重点,今天我们更详细的来研究一下View的onMeasure()方法和ViewGroup的onMeasure()方法 2 ...

  6. devcpp中很简单的排序

    之前学的东西,不知什么缺了,什么没缺,索性重头开始弄,用的是<啊哈!算法>. 排序很简单,小的可以选择死磕.直接贴一份代码. #include<iostream> #inclu ...

  7. 性能测试培训:批量执行Jmeter脚本之ant调用

    性能测试培训:批量执行Jmeter脚本之ant调用   poptest是国内唯一一家培养测试开发工程师的培训机构,以学员能胜任自动化测试,性能测试,测试工具开发等工作为目标.在poptest的load ...

  8. MongoDB--在windows下的安装过程及基本配置

    这几天在做一个简单的后台博客系统,数据库用到了 MongoDB ,虽说官方的文档比较全,但是对于我一个英语一般的人来说,或多或少在配置的时候出现了一些问题,总结了一下在安装及创建服务的过程 Mongo ...

  9. 读《effective C++》1

    条款一:视C++为一个语言联邦 学习C++半个月了,学了他的面向过程编程,面向对象编程(封装性,继承性,多态性),template泛型编程,开始只是觉得C++基础是面向对象,但是学了这么多块开始有点迷 ...

  10. 关于string类型定义占几个字节??

    测试代码: #include <iostream>using namespace std;int main(void){ string name; cout<<"si ...