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 ...
随机推荐
- [Spark][Flume]Flume 启动例子
Flume 启动例子: flume-ng agent --conf /etc/flume-ng/conf --conf-file /etc/flume-ng/conf/flume.conf --nam ...
- 分布式系统消息中间件——RabbitMQ的使用思考篇
分布式系统消息中间件--RabbitMQ的使用思考篇 前言 前面的两篇文章分布式系统消息中间件--RabbitMQ的使用基础篇与分布式系统消息中间件--RabbitMQ的使用进阶篇,我们简单介 ...
- Python股票分析系列——数据整合.p7
欢迎来到Python for Finance教程系列的第7部分. 在之前的教程中,我们为整个标准普尔500强公司抓取了雅虎财经数据. 在本教程中,我们将把这些数据组合到一个DataFrame中. 到此 ...
- 如何用CSS3画出一个立体魔方?
前言 最近在写<动画点点系列>文章,上一期分享了< 手把手教你如何绘制一辆会跑车 >,本期给大家带来是结合CSS3画出来的一个立体3d魔方,结合了js让你随心所欲想怎么转,就怎 ...
- LeetCode 905. Sort Array By Parity
905. Sort Array By Parity Given an array A of non-negative integers, return an array consisting of a ...
- centos6.5 squid安装
squid作用 1正向代理 标准的代理缓冲服务器,须在每一个内部主机的浏览器上明确指明代理服务器的IP地址和端口号. 透明代理缓冲服务器,代理操作对客户端的浏览器是透明的(即不需指明代理服务器的IP和 ...
- 小谈UAT(验收测试)
验收测试人员的测试任务: 1.验收人员是提出需求的人员,所以对需求最为熟悉,最主要测试功能的遗漏或者多余2.系统测试人员重点在测试功能的正确性和非功能的符合性,当然也希望验收人员测试功能的正确性3.因 ...
- 牛客练习赛38 D 题 出题人的手环 (离散化+树状数组求逆序对+前缀和)
链接:https://ac.nowcoder.com/acm/contest/358/D来源:牛客网 出题人的手环 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 524288K,其他 ...
- 解决sqoop连接mysq错误
一.问题描述 1.由于当前集群没有配置Zookeeper.hcatalog.accumlo,因此应该在sqoop的配置文件中注释掉判断Zookeeper.hcatalog.accumlo路径是否正确的 ...
- Java ME Technology - CDC(Connected Device Configuration)
Java ME Technology - CDChttps://www.oracle.com/technetwork/java/javame/tech/index-jsp-139293.html Ne ...