Java并发编程之线程池任务监控
当我们提交runnable或者callable<?>到ThreadPoolExecutor时,我们是无法知道这些任务是在什么时候才真正的执行的,为了实现这个需求,我们需要扩展ThreadPoolExecutor,重写beforeExecute和afterExecute,在这两个方法里分别做一些任务执行前和任务执行后的相关监控逻辑,还有个terminated方法,是在线程池关闭后回调,,另外,我们可以通过getLargestPoolSize()和getCompletedTaskCount()来分别获取线程池数的峰值和线程池已完成的任务数。
下面就一个完整的例子来说明如何进行:
自定义MonitorHandler接口,把before和after抽象出来:
- package cc.lixiaohui.demo.concurrent;
- /**
- * 监控处理器, 目的是把before和after抽象出来, 以便在{@link MonitorableThreadPoolExecutor}中形成一条监控处理器链
- *
- * @author lixiaohui
- * @date 2016年10月11日 下午7:18:38
- *
- */
- public interface MonitorHandler {
- /**
- * 改监控任务是否可用
- *
- * @return
- */
- boolean usable();
- /**
- * 任务执行前回调
- *
- * @param thread 即将执行该任务的线程
- * @param runnable 即将执行的任务
- */
- void before(Thread thread, Runnable runnable);
- /**
- * <pre>
- * 任务执行后回调
- * 注意:
- * 1.当你往线程池提交的是{@link Runnable} 对象时, 参数runnable就是一个{@link Runnable}对象
- * 2.当你往线程池提交的是{@link java.util.concurrent.Callable<?>} 对象时, 参数runnable实际上就是一个{@link java.util.concurrent.FutureTask<?>}对象
- * 这时你可以通过把参数runnable downcast为FutureTask<?>或者Future来获取任务执行结果
- *
- * @param runnable 执行完后的任务
- * @param throwable 异常信息
- */
- void after(Runnable runnable, Throwable throwable);
- /**
- * 线程池关闭后回调
- *
- * @param largestPoolSize
- * @param completedTaskCount
- */
- void terminated(int largestPoolSize, long completedTaskCount);
- }
扩展ThreadPoolExecutor,增加监控的逻辑,如果监控比较耗时的话,为了不影响业务线程池的执行效率,我们应该将before,after和terminated方法的调用封装为统一的Runnable交给非业务线程池内的Thread来跑(新建个Thread或者线程池):
- package cc.lixiaohui.demo.concurrent;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.concurrent.BlockingQueue;