若直接使用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;}@Overridepublic 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);}@Overridepublic void execute(Runnable task) {super.execute(wrap(task, clientTrace(), Thread.currentThread().getName()));}@Overridepublic 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" 100503325java.lang.ArithmeticException: / by zeroat 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 traceat 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 zeroat concurrent.C03_TraceThreadPoolExecutor$MyTask.run(C03_TraceThreadPoolExecutor.java:16)100503325at 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)
