欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。

欢迎跳转到本文的原文链接:https://honeypps.com/java/java-multi-thread-of-thread-pool-executor/

ThreadPoolExecutor是可扩展的,通过查看源码可以发现,它提供了几个可以在子类化中改写的方法:beforeExecute,afterExecute,terminated.

源码片段如下所示:

protected void beforeExecute(Thread t, Runnable r) { }
protected void afterExecute(Runnable r, Throwable t) { }
protected void terminated() { }

可以注意到,这三个方法都是protected的空方法,摆明了是让子类扩展的嘛。

在执行任务的线程中将调用beforeExecute和afterExecute等方法,在这些方法中还可以添加日志、计时、监视或者统计信息收集的功能。无论任务是从run中正常返回,还是抛出一个异常而返回,afterExecute都会被调用。如果任务在完成后带有一个Error,那么就不会调用afterExecute。如果beforeExecute抛出一个RuntimeException,那么任务将不被执行,并且afterExecute也不会被调用。

在线程池完成关闭时调用terminated,也就是在所有任务都已经完成并且所有工作者线程也已经关闭后,terminated可以用来释放Executor在其生命周期里分配的各种资源,此外还可以执行发送通知、记录日志或者手机finalize统计等操作。

下面就以给线程池添加统计信息为例(添加日志和及时等功能):

package com.threadPool;import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger;public class TimingThreadPool extends ThreadPoolExecutor
{private final ThreadLocal<Long> startTime = new ThreadLocal<Long>();private final Logger log = Logger.getAnonymousLogger();private final AtomicLong numTasks = new AtomicLong();private final AtomicLong totalTime = new AtomicLong();public TimingThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,BlockingQueue<Runnable> workQueue){super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);}protected void beforeExecute(Thread t, Runnable r){super.beforeExecute(t, r);log.info(String.format("Thread %s: start %s", t,r));startTime.set(System.nanoTime());}protected void afterExecute(Runnable r, Throwable t){try{long endTime = System.nanoTime();long taskTime = endTime-startTime.get();numTasks.incrementAndGet();totalTime.addAndGet(taskTime);log.info(String.format("Thread %s: end %s, time=%dns", t,r,taskTime));}finally{super.afterExecute(r, t);}}protected void terminated(){try{log.info(String.format("Terminated: avg time=%dns",totalTime.get()/numTasks.get()));}finally{super.terminated();}}
}

可以看到TimingThreadPool重写了父类的三个方法。

下面写一个测试类,参考运行效果:

package com.threadPool;import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;public class CheckTimingThreadPool
{public static void main(String[] args){ThreadPoolExecutor  exec = new TimingThreadPool(0, Integer.MAX_VALUE,60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>());exec.execute(new DoSomething(5));exec.execute(new DoSomething(4));exec.execute(new DoSomething(3));exec.execute(new DoSomething(2));exec.execute(new DoSomething(1));exec.shutdown();}}class DoSomething implements Runnable{private int sleepTime;public DoSomething(int sleepTime){this.sleepTime = sleepTime;}@Overridepublic void run(){System.out.println(Thread.currentThread().getName()+" is running.");try{TimeUnit.SECONDS.sleep(sleepTime);}catch (InterruptedException e){e.printStackTrace();}}}

运行结果:

十二月 25, 2015 4:18:42 下午 com.threadPool.TimingThreadPool beforeExecute
信息: Thread Thread[pool-1-thread-1,5,main]: start com.threadPool.DoSomething@43f459c2
十二月 25, 2015 4:18:42 下午 com.threadPool.TimingThreadPool beforeExecute
信息: Thread Thread[pool-1-thread-3,5,main]: start com.threadPool.DoSomething@33891d5d
pool-1-thread-3 is running.
十二月 25, 2015 4:18:42 下午 com.threadPool.TimingThreadPool beforeExecute
信息: Thread Thread[pool-1-thread-4,5,main]: start com.threadPool.DoSomething@33891d5d
pool-1-thread-4 is running.
十二月 25, 2015 4:18:42 下午 com.threadPool.TimingThreadPool beforeExecute
信息: Thread Thread[pool-1-thread-5,5,main]: start com.threadPool.DoSomething@10747b4
pool-1-thread-5 is running.
十二月 25, 2015 4:18:42 下午 com.threadPool.TimingThreadPool beforeExecute
信息: Thread Thread[pool-1-thread-2,5,main]: start com.threadPool.DoSomething@7d4af469
pool-1-thread-2 is running.
pool-1-thread-1 is running.
十二月 25, 2015 4:18:43 下午 com.threadPool.TimingThreadPool afterExecute
信息: Thread null: end com.threadPool.DoSomething@10747b4, time=999589906ns
十二月 25, 2015 4:18:44 下午 com.threadPool.TimingThreadPool afterExecute
信息: Thread null: end com.threadPool.DoSomething@33891d5d, time=1999461618ns
十二月 25, 2015 4:18:45 下午 com.threadPool.TimingThreadPool afterExecute
信息: Thread null: end com.threadPool.DoSomething@33891d5d, time=3000507593ns
十二月 25, 2015 4:18:46 下午 com.threadPool.TimingThreadPool afterExecute
信息: Thread null: end com.threadPool.DoSomething@7d4af469, time=3999691253ns
十二月 25, 2015 4:18:47 下午 com.threadPool.TimingThreadPool afterExecute
信息: Thread null: end com.threadPool.DoSomething@43f459c2, time=4999778490ns
十二月 25, 2015 4:18:47 下午 com.threadPool.TimingThreadPool terminated
信息: Terminated: avg time=2999805772ns

可以看到,在测试类CheckTimingThreadPool中通过execute了五个线程,然后分别对这五个线程进行统计,最后统计出各个线程的耗时平均时间。

这里说明下TimingThreadPool的构造函数,它直接调用了父类的构造方法,在ThreadPoolExecutor中有许多构造方法,有兴趣的朋友可以查看jdk api或者源码进行查看。

简要说明下构造函数的参数的含义:

corePoolSize:线程池维护线程的最少数量

maximumPoolSize:线程池维护线程的最大数量

keepAliveTime:线程池维护线程所允许的空闲时间

unit:线程池维护所允许的空闲时间的单位

workQueue:线程池所使用的缓存队列

欢迎跳转到本文的原文链接:https://honeypps.com/java/java-multi-thread-of-thread-pool-executor/

欢迎支持笔者新作:《深入理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。

JAVA多线程之扩展ThreadPoolExecutor相关推荐

  1. java多线程系列:ThreadPoolExecutor源码分析

    前言 这篇主要讲述ThreadPoolExecutor的源码分析,贯穿类的创建.任务的添加到线程池的关闭整个流程,让你知其然所以然.希望你可以通过本篇博文知道ThreadPoolExecutor是怎么 ...

  2. java多线程系列:ThreadPoolExecutor源码分析,java基础面试笔试题

    我总结出了很多互联网公司的面试题及答案,并整理成了文档,以及各种学习的进阶学习资料,免费分享给大家. 扫描二维码或搜索下图红色VX号,加VX好友,拉你进[程序员面试学习交流群]免费领取.也欢迎各位一起 ...

  3. java 多线程池_Java ThreadPoolExecutor线程池 同时执行50个线程

    最近项目上有个需求,需要从FTP服务器中下载大批量的数据文件,然后解析该数据文件进行入库,数据库为oracle,最后在通过web工程,以报表和图表的形式进行展现. 这些批量的数据文件为纯文本文件,每天 ...

  4. Java多线程知识小抄集(四)——完结

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  5. Java多线程知识小抄集(三)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  6. Java多线程知识小抄集(二)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  7. Java多线程知识小抄集(一)

    欢迎支持笔者新作:<深入理解Kafka:核心设计与实践原理>和<RabbitMQ实战指南>,同时欢迎关注笔者的微信公众号:朱小厮的博客. 欢迎跳转到本文的原文链接:https: ...

  8. java 多线程 一个博客

    http://blog.csdn.net/a352193394/article/category/2563875 Java多线程之~~~线程安全容器的非阻塞容器 在并发编程中,会经常遇到使用容器.但是 ...

  9. Java多线程学习详细学习及扩展

    Java多线程详细学习及扩展 学习视频:b站狂神–多线程篇 一.概述 1.1.名词解释 程序(application):程序是指令和数据的有序集合,其本身没有任何的运行的含义,是一个静态的概念. 进程 ...

最新文章

  1. 10的多少次方 oracle_初中数学:关于一元二次方程的中考经典例题,千万别错过!...
  2. android中变量作用域,在 Android 和 Hilt 中限定作用域
  3. Fiddler建好代理后,能连到手机,但手机不能上网了,求破有果
  4. powermock跳过某方法_变频调速电动机产生机械共振原因和处理方法
  5. subprogram or cursor is declared in a package specification and must be defined in the package body
  6. 队列与环形队列使用数组模拟
  7. 静态代理、动态代理、AOP
  8. 信息安全工程师笔记-云计算安全需求分析与安全保护工程
  9. zabbix详解(二)——zabbix工作原理
  10. 爬虫介绍+Jupyter Notebook
  11. greenplum客户端工具_GreenPlum数据加载工具gpload | 信春哥,系统稳,闭眼上线不回滚!...
  12. python定义一个空的数组_用Python算算你要交多少个人所得税
  13. USB免驱NFC读写器 Android系统中NFC读写范例
  14. 微信公众号跳转到关注页面
  15. 来看一看 Google 给你的标签是什么
  16. echarts社区饼图 echart饼图 玫瑰图
  17. 计算机关机界面设置在哪里,如何修改电脑关机图片_win7电脑关机背景怎么设置图文教程...
  18. 显示器间歇性黑屏问题排查
  19. 3.5亿!创维电视董事长双11直播带货,哪些细节值得借鉴?
  20. linux编程获取本机IP地址的三种方法

热门文章

  1. 结合webpack配置_前端 Webpack 工程化的最佳实践
  2. 实习笔记0708 https协议/ django中间件/接口测试/内网与外网/域名系统DNS
  3. 共模干扰和差模干扰(图解)---摘自: 硬件十万个为什么
  4. JAVA面试题(20)
  5. [NOI2018]你的名字
  6. 反射和代理的具体应用
  7. 设计模式C++实现--Interpreter模式
  8. linux cache and buffer【转】
  9. css 实现table 隔行变色
  10. ASP.NET MVC与RAILS3的比较