Java自定义线程池-记录每个线程执行耗时
ThreadPoolExecutor是可扩展的,其提供了几个可在子类化中改写的方法,如下:
- protected void beforeExecute(Thread t, Runnable r) { }
- protected void afterExecute(Runnable r, Throwable t) { }
- protected void terminated() { }
现基于此,完成一个统计每个线程执行耗时,并计算平均耗时的 自定义线程池样例。通过 beforeExecute、afterExecute、terminated 方法来添加日志记录和统计信息收集。为了测量任务的运行时间,beforeExecute必须记录开始时间并把它保存到一个ThreadLocal变量中,然后由afterExecute来读取。同时,使用两个 AtomicLong变量,分别用以记录已处理的任务数和总的处理时间,并通过terminated来输出包含平均任务时间的日志消息。
自定义线程池代码如下:
- 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<>();
- private final Logger log = Logger.getLogger("TimingThreadPool");
- 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);
- }
- @Override
- 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());
- }
- @Override
- 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);
- }
- }
- @Override
- protected void terminated() {
- try {
- log.info(String.format("Terminated: avg time=%dns",totalTime.get() / numTasks.get()));
- } finally {
- super.terminated();
- }
- }
- }
测试执行效果代码如下:
- import java.util.ArrayList;
- import java.util.List;
- import java.util.concurrent.Callable;
- import java.util.concurrent.Future;
- import java.util.concurrent.LinkedBlockingQueue;
- import java.util.concurrent.TimeUnit;
- /**
- * 测试自定义线程池
- */
- public class TestCustomThreadPool {
- public static void main(String[] args) {
- try {
- TimingThreadPool threadPool = new TimingThreadPool(,,0L, TimeUnit.MILLISECONDS,
- new LinkedBlockingQueue<Runnable>());
- List<TestCallable> tasks = new ArrayList<>();
- for (int i = ; i < ; i++) {
- tasks.add(new TestCallable());
- }
- List<Future<Long>> futures = threadPool.invokeAll(tasks);
- for (Future<Long> future :
- futures) {
- System.out.print(" - "+future.get());
- }
- threadPool.shutdown();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- static class TestCallable implements Callable<java.lang.Long> {
- @Override
- public Long call() throws Exception {
- long total = ;
- for (int i = ; i < ; i++) {
- long now = getRandom();
- total += now;
- }
- Thread.sleep(total);
- return total;
- }
- public long getRandom () {
- return Math.round(Math.random() * );
- }
- }
- }
执行结果:
Java自定义线程池-记录每个线程执行耗时的更多相关文章
- Java如何判断线程池所有任务是否执行完毕
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Tes ...
- Java 线程池记录
Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...
- Java多线程系列--“JUC线程池”03之 线程池原理(二)
概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...
- Java多线程系列--“JUC线程池”04之 线程池原理(三)
转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...
- Java线程池二:线程池原理
最近精读Netty源码,读到NioEventLoop部分的时候,发现对Java线程&线程池有些概念还有困惑, 所以深入总结一下 Java线程池一:线程基础 为什么需要使用线程池 Java线程映 ...
- Java多线程系列--“JUC线程池”01之 线程池架构
概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容——线程池.内容包括:线程池架构 ...
- Java多线程系列--“JUC线程池”02之 线程池原理(一)
概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...
- Java多线程系列--“JUC线程池”05之 线程池原理(四)
概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...
- 深入浅出 Java Concurrency (34): 线程池 part 7 线程池的实现及原理 (2)[转]
线程池任务执行流程 我们从一个API开始接触Executor是如何处理任务队列的. java.util.concurrent.Executor.execute(Runnable) Executes t ...
随机推荐
- NLTK 第一篇:介绍
NLTK(Natural Language Toolkit)是一个功能强大的自然语言处理工具,它提供了一组自然语言算法,例如切分词(Tokenize),词性标注(Part-Of-Speech Tagg ...
- Python从菜鸟到高手(8):print函数、赋值与代码块
1.神奇的print函数 print函数相信读者一定对它不陌生,因为在前面的章节,几乎每个例子都使用了print函数,这个函数的功能就是在控制台输出文本.不过print在输出文本时还可以进行一些设 ...
- C#(.NET) HMAC SHA256实现
HMAC SHA256的实现比较简单,可以用多种语言实现,下面我用C#语言实现,一种结果是居于BASE64,另外一种是居于64位. C# HMAC SHA256 (Base64) using Syst ...
- eclipse 常用配置
一.内置tomcat配置 解决eclipse 内置tomcat 与本地tomcat 端口冲突 传送门:http://www.cnblogs.com/tweet/p/7568979.html 二.字体设 ...
- tensorflow-gpu安装的一些注意
按正确的顺序安装,严格安装特定的版本 1,下载和安装严格版本的cuda和cuDnn,其他版本的不干活.比如要求9.0你就不能装9.1.https://www.tensorflow.org/instal ...
- [蛙蛙推荐]SICP第一章学习笔记-编程入门
本书简介 <计算机程序的构造与解释>这本书是MIT计算机科学学科的入门课程, 大部分学生在学这门课程前都没有接触过程序设计,也就是说这本书是针对编程新手写的. 虽然是入门课程,但起点比较高 ...
- 根据指定条件使CheckBox 无法选中
var trList = $("#tab1").children("tr")for (var i=0;i<trList.length;i++) {var ...
- shell 读取配置文件的方法
原文地址:http://bbs.chinaunix.net/thread-3628456-1-1.html 总结地址:https://www.cnblogs.com/binbinjx/p/568021 ...
- Dapper-小型ORM之王(C#.NET)
ORM:对象关系映射器,它直接将数据库映射到C#对象. 有很多ORM框架可用,Dapper是其中之一,被称为ORM之王. 下面是Dapper主要的一些功能: 速度快,性能好; 更少的代码行 对象映射 ...
- Python_%---format_43
fat39 博客园 首页 新随笔 联系 订阅 管理 随笔 - 142 文章 - 0 评论 - 0 python基础_格式化输出(%用法和format用法) 目录 %用法 format用法 %用 ...