帶日誌和計時等功能的執行緒池
阿新 • • 發佈:2018-12-01
帶日誌和計時等功能的執行緒池
歡迎關注作者部落格
簡書傳送門
前言
我們先來聊聊ThreadPoolExecutor的拓展。
擴充套件ThreadPoolExecutor
在執行任務的執行緒中將呼叫beforeExecute和afterExecute等方法,在這些方法中還可以新增日誌、計時、監視或者統計資訊收集的功能。無論任務是從run中正常返回,還是丟擲一個異常而返回,afterExecute都會被呼叫。如果任務在完成後帶有一個Error,那麼就不會呼叫afterExecute。如果beforeExecute丟擲一個RuntimeException,那麼任務將不被執行,並且afterExecute也不會被呼叫。
線上程池完成關閉時呼叫terminated,也就是在所有任務都已經完成並且所有工作者執行緒也已經關閉後,terminated可以用來釋放Executor在其生命週期裡分配的各種資源,此外還可以執行傳送通知、記錄日誌或者手機finalize統計等操作。
ThreadPoolExecutor使用了模板方法模式,提供了beforeExecute、afterExecute和terminated擴充套件方法。
- 執行緒執行前呼叫beforeExecute(如果beforeExecute丟擲了一個RuntimeException,那麼任務將不會被執行)
- 執行緒執行後呼叫afterExecute(丟擲異常也會呼叫,如果任務在完成後帶有一個Error,那麼就不會呼叫afterExecute)
- 線上程池完成關閉操作時呼叫terminated,也就是所有任務都已經完成並且所有工作者執行緒也已經關閉後
原始碼
/**
* @program:
* @description: 具備日誌和計時等功能的執行緒池
* @author: zhouzhixiang
* @create: 2018-11-14 20:40
*/
public class TimingThreadPool extends ThreadPoolExecutor{
private final ThreadLocal<Long> starttime = new ThreadLocal< >();
private final AtomicLong numtask = new AtomicLong();
private final AtomicLong totaltime = new AtomicLong();
private final Logger logger = Logger.getLogger("TimingThreadPool");
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);
logger.fine(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() - starttime.get();
totaltime.addAndGet(endtime);
numtask.incrementAndGet();
logger.fine(String.format("Thread %s: end %s, time=%dns", t, r, totaltime));
}finally {
super.afterExecute(r, t);
}
}
@Override
protected void terminated() {
try{
logger.info(String.format("Terminated: avg time=%dns", totaltime.get() / numtask.get()));
}finally {
super.terminated();
}
}
}
歡迎加入Java猿社群