若直接使用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)