钩子方法的优点:
beforeExecute(Thread, Runnable)
和afterExecute(Runnable, Throwable)
:
beforeExecute(Thread, Runnable)
和afterExecute(Runnable, Throwable)
方法会在每个任务执行前后被调用。这些方法可以用于操作执行环境,例如重新初始化ThreadLocals、收集统计数据或添加日志条目。
我正在使用自定义ThreadPoolExecutor
来处理未捕获的异常。我可以在Runnable
和Callable
中添加try{} catch{}
块,但是假设遇到无法强制开发人员在相关的Runnable
和Callable
任务中添加这些块的情况。
这个CustomThreadPoolExecutor
覆盖了ThreadPoolExecutor
中的afterExecute()
方法如下(我已将变量b的值分配为零以模拟算术异常):
import java.util.concurrent.*;
import java.util.*;
class CustomThreadPoolExecutor extends ThreadPoolExecutor {
public CustomThreadPoolExecutor() {
super(1,10,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1000));
}
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
System.out.println(result);
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
t.printStackTrace();
}
}
public class CustomThreadPoolExecutorDemo{
public static void main(String args[]){
System.out.println("creating service");
//ExecutorService service = Executors.newFixedThreadPool(10);
CustomThreadPoolExecutor service = new CustomThreadPoolExecutor();
service.submit(new Runnable(){
public void run(){
int a=4, b = 0;
System.out.println("a and b="+a+":"+b);
System.out.println("a/b:"+(a/b));
System.out.println("Thread Name in Runnable after divide by zero:"+Thread.currentThread().getName());
}
});
service.shutdown();
}
}
由于submit()
在框架中隐藏了异常,因此我重写了afterExecute()
方法来捕获异常。
在这个方法中,我添加了以下语句的阻塞调用
Object result = ((Future<?>) r).get();
目前我有10个线程,队列容量为1000。假设我的Runnable
需要5秒钟才能完成。
通过重写afterExecute
()方法,这种方法是否会增加任何性能开销或者存在任何缺点?