带日志和计时等功能的线程池

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/danielzhou888/article/details/84074366

带日志和计时等功能的线程池

欢迎关注作者博客
简书传送门

前言

  我们先来聊聊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猿社区
欢迎加入Java猿社区.png

猜你喜欢

转载自blog.csdn.net/danielzhou888/article/details/84074366