在实际开发中使用线程池时,通常我们都不会直接使用如下的方式来创建一个线程池,而是通过新建ThreadPoolExecutor对象或者继承ThreadPoolExecutor类,及配置相关属性来新建一个线程池,这样有很多好处大家都知道,有什么不太清楚的可以参照 Executor 框架小结一文。
ExecutorService executorService = Executors.newFixedThreadPool(10);
ExecutorService executorService2 = Executors.newSingleThreadExecutor();
ExecutorService executorService3 = Executors.newCachedThreadPool();
那么如何对我们新建的进行扩展呢?我们在这里采用的是新建一个继承ThreadPoolExecutor的类AroundThreadPool,扩展的功能是beforeExecute方法和afterExecute方法,这两个方法都是ThreadPoolExecutor类中空实现的方法,我们可以在AroundThreadPool类中重写。
protected void beforeExecute(Thread t, Runnable r) { }
protected void afterExecute(Runnable r, Throwable t) { }
重写的功能主要是,对已处理的任务的计数和处理时间的监控,具体代码如下:
public class AroundThreadPool extends ThreadPoolExecutor {
public AroundThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
}
private final ThreadLocal<Long> startTime = new ThreadLocal<Long>();
private final Logger log = Logger.getLogger("AroundThreadPool");
private final AtomicLong numTasks = new AtomicLong();
private final AtomicLong totalTime = new AtomicLong();
@Override
protected void beforeExecute(Thread t, Runnable r) {
super.beforeExecute(t, r);
log.fine(String.format("Thread %s: start %s", t, r));
startTime.set(System.nanoTime());
System.out.println(startTime);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
long endTime = System.nanoTime();
long taskTime = endTime - startTime.get();
numTasks.incrementAndGet();
totalTime.addAndGet(taskTime);
log.fine(String.format("Thread %s: end %s, time=%dns", t, r, taskTime));
super.afterExecute(r, t);
System.out.println(endTime);
}
}
大致上 我们可以对任务进行简单的监控了。
测试类的代码:
public static void main(String[] args) {
ExecutorService scheduledExecutorService = new AroundThreadPool(5, 10, 60, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1000),
new ThreadPoolExecutor.AbortPolicy());
for (int i = 0; i < 80; i++) {
scheduledExecutorService.submit(new Runnable() {
@Override
public void run() {
System.out.println("hhh");
}
});
}
}