若直接使用ThreadPoolExecutor講沒法獲得線程的異常信息,因此在這裏對ThreadPoolExecutor進行增強java
自定義任務類ide
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; } }; } }
測試ThreadPoolExecutorthis
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)
雖然控制檯提示咱們有錯誤,可是咱們並不知道錯誤發生在什麼地方,這不利於咱們定位錯誤。code
測試TraceThreadPoolExecutorget
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(); }
consoleit
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)