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自定义线程池-记录每个线程执行耗时的更多相关文章

  1. Java如何判断线程池所有任务是否执行完毕

    import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Tes ...

  2. Java 线程池记录

    Java通过Executors提供四种线程池,分别为:newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程.newFixe ...

  3. Java多线程系列--“JUC线程池”03之 线程池原理(二)

    概要 在前面一章"Java多线程系列--“JUC线程池”02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代 ...

  4. Java多线程系列--“JUC线程池”04之 线程池原理(三)

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509960.html 本章介绍线程池的生命周期.在"Java多线程系列--“基础篇”01之 基 ...

  5. Java线程池二:线程池原理

    最近精读Netty源码,读到NioEventLoop部分的时候,发现对Java线程&线程池有些概念还有困惑, 所以深入总结一下 Java线程池一:线程基础 为什么需要使用线程池 Java线程映 ...

  6. Java多线程系列--“JUC线程池”01之 线程池架构

    概要 前面分别介绍了"Java多线程基础"."JUC原子类"和"JUC锁".本章介绍JUC的最后一部分的内容——线程池.内容包括:线程池架构 ...

  7. Java多线程系列--“JUC线程池”02之 线程池原理(一)

    概要 在上一章"Java多线程系列--“JUC线程池”01之 线程池架构"中,我们了解了线程池的架构.线程池的实现类是ThreadPoolExecutor类.本章,我们通过分析Th ...

  8. Java多线程系列--“JUC线程池”05之 线程池原理(四)

    概要 本章介绍线程池的拒绝策略.内容包括:拒绝策略介绍拒绝策略对比和示例 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3512947.html 拒绝策略 ...

  9. 深入浅出 Java Concurrency (34): 线程池 part 7 线程池的实现及原理 (2)[转]

    线程池任务执行流程 我们从一个API开始接触Executor是如何处理任务队列的. java.util.concurrent.Executor.execute(Runnable) Executes t ...

随机推荐

  1. C#.NET 大型通用信息化系统集成快速开发平台 4.1 版本 - 对外不要提供Delete方法加强软件的安全性

    1:软件系统一般不怕外面的人,最怕有内鬼.2:软件系统不怕一万,就怕万一,最好不要对外有漏洞,能不提供Delete方法就不提供.3:特别是不要有能远程调用的Delete方法,那就是出了事情都无法找到是 ...

  2. 第四次oo博客

    论述测试与正确性论证的效果差异 单元测试利用测试者构造的测试用例来检查类或方法的正确性,一般来说所需要测试的用例是无穷多的,通过人为构造代表性的测试用例来尽量测试所有代码.测试的优点在于不易出错,只要 ...

  3. 【转载】KETTLE集群搭建

    一.集群的原理与优缺点 1.1集群的原理 Kettle集群是由一个主carte服务器和多个从carte服务器组成的,类似于master-slave结构,不同的是’master’处理具体任务,只负责任务 ...

  4. 使用HDTune规避硬盘上损坏的扇区

    如何使用HDTune扫描磁盘上的错误在网上已经有很多帖子了,但扫描到之后如何用HDTune来规避硬盘上损坏的扇区呢? HDTune并不能直接规避,而是需要重新划分磁盘的卷.HDTune一行有50个小方 ...

  5. Python_内置函数之round的幺蛾子

    pycharm运行结果 1 ret = round(0.5) print(ret) >>> 0 ret1 = round(1.5) print(ret1) >>> ...

  6. CentOS下配置SS5(SOCKS5)代理服务器

    方案:使用开源的SS5( Socks Server 5 ) 官网:http://ss5.sourceforge.net/ (点击左侧的Software在右侧的Server处进入下载地址) CentOs ...

  7. SQL性能优化-order by语句的优化

    原文:http://bbs.landingbj.com/t-0-243203-1.html 在某些情况中,MySQL可以使用一个索引来满足ORDER BY子句,而不需要额外的排序.where条件和or ...

  8. [转帖]xargs命令详解,xargs与管道的区别

    xargs命令详解,xargs与管道的区别 https://www.cnblogs.com/wangqiguo/p/6464234.html 之前一直说要学习一下 xargs 到现在为止也没学习.. ...

  9. php变量详解

    变量是用于存储信息的"容器". 定义一个变量的语法: $变量名 = 值; 使用变量的例子: <?php $x=5; $y=6; $z=$x+$y; echo $z; ?> ...

  10. JS --- 本地保存localStorage、sessionStorage用法总结

    JS的本地保存localStorage.sessionStorage用法总结 localStorage.sessionStorage是Html5的特性,IE7以下浏览器不支持 为什么要掌握localS ...