若直接使用ThreadPoolExecutor将无法得到线程的异常信息,所以在这里对ThreadPoolExecutor进行加强
自定义任务类
public static class MyTask implements Runnable{
private int a;
private int b;
public MyTask(int a, int b){this.a = a; this.b = b;}
@Override
public void run() {
System.out.println(a/b);
}
}
自定义线程池
public static class TraceThreadPoolExecutor extends ThreadPoolExecutor{
public TraceThreadPoolExecutor(int corePoolSize, int maximumPoolSize
, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
public void execute(Runnable task) {
super.execute(wrap(task, clientTrace(), Thread.currentThread().getName()));
}
@Override
public Future<?> submit(Runnable task) {
return super.submit(wrap(task, clientTrace(), Thread.currentThread().getName()));
}
private Exception clientTrace(){
return new Exception("Client stack trace");
}
//通过一个新的Runnable的run方法来包装task的run方法,
// 两个参数都使用final,这样新的Runnable在使用task和clientStack就不会出错了。
private Runnable wrap(final Runnable task, final Exception clientStack, String clientThreadName){
return () -> {
try{
task.run(); //后续会在这里执行线程
} catch (Exception e){
clientStack.printStackTrace(); //若线程发生错误会在这里打印异常信息
throw e;
}
};
}
}
测试ThreadPoolExecutor
public static void main(String[] args){
ThreadPoolExecutor pe =
new ThreadPoolExecutor(0, 10, 30L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
// new TraceThreadPoolExecutor(0, 10,30L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
for(int i=0 ; i<5 ; i++){
// pe.submit(new MyTask(100, i));
pe.execute(new MyTask(100, i));
/* ThreadPoolExecutor.submit,不会打印任何错误信息
* ThreadPoolExecutor.execute,打印线程异常信息
* TraceThreadPoolExecutor.submit,只打印部分信息(哪里创建了异常线程)
* TraceThreadPoolExecutor.execute,打印了全部异常信息(包括创建异常线程的位置,已经哪里发生了异常)
*/
}
pe.shutdown();
}
console
Exception in thread "pool-1-thread-1" 100
50
33
25
java.lang.ArithmeticException: / by zero
at concurrent.C03_TraceThreadPoolExecutor$MyTask.run(C03_TraceThreadPoolExecutor.java:16)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
虽然控制台提示我们有错误,但是我们并不知道错误发生在什么地方,这不利于我们定位错误。
测试TraceThreadPoolExecutor
public static void main(String[] args){
ThreadPoolExecutor pe =
new TraceThreadPoolExecutor(0, 10,30L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
for(int i=0 ; i<5 ; i++){
// pe.submit(new MyTask(100, i));
pe.execute(new MyTask(100, i));
/* ThreadPoolExecutor.submit,不会打印任何错误信息
* ThreadPoolExecutor.execute,打印线程异常信息
* TraceThreadPoolExecutor.submit,只打印部分信息(哪里创建了异常线程)
* TraceThreadPoolExecutor.execute,打印了全部异常信息(包括创建异常线程的位置,已经哪里发生了异常)
*/
}
pe.shutdown();
}
console
java.lang.Exception: Client stack trace
at concurrent.C03_TraceThreadPoolExecutor$TraceThreadPoolExecutor.clientTrace(C03_TraceThreadPoolExecutor.java:36)
at concurrent.C03_TraceThreadPoolExecutor$TraceThreadPoolExecutor.execute(C03_TraceThreadPoolExecutor.java:27)
at concurrent.C03_TraceThreadPoolExecutor.main(C03_TraceThreadPoolExecutor.java:63)
Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
at concurrent.C03_TraceThreadPoolExecutor$MyTask.run(C03_TraceThreadPoolExecutor.java:16)
100
50
33
25
at concurrent.C03_TraceThreadPoolExecutor$TraceThreadPoolExecutor.lambda$0(C03_TraceThreadPoolExecutor.java:44)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)