若直接使用ThreadPoolExecutor将无法得到线程的异常信息,所以在这里对ThreadPoolExecutor进行加强


    自定义任务类

    1. public static class MyTask implements Runnable{
    2. private int a;
    3. private int b;
    4. public MyTask(int a, int b){this.a = a; this.b = b;}
    5. @Override
    6. public void run() {
    7. System.out.println(a/b);
    8. }
    9. }

    自定义线程池

    1. public static class TraceThreadPoolExecutor extends ThreadPoolExecutor{
    2. public TraceThreadPoolExecutor(int corePoolSize, int maximumPoolSize
    3. , long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
    4. super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
    5. }
    6. @Override
    7. public void execute(Runnable task) {
    8. super.execute(wrap(task, clientTrace(), Thread.currentThread().getName()));
    9. }
    10. @Override
    11. public Future<?> submit(Runnable task) {
    12. return super.submit(wrap(task, clientTrace(), Thread.currentThread().getName()));
    13. }
    14. private Exception clientTrace(){
    15. return new Exception("Client stack trace");
    16. }
    17. //通过一个新的Runnable的run方法来包装task的run方法,
    18. // 两个参数都使用final,这样新的Runnable在使用task和clientStack就不会出错了。
    19. private Runnable wrap(final Runnable task, final Exception clientStack, String clientThreadName){
    20. return () -> {
    21. try{
    22. task.run(); //后续会在这里执行线程
    23. } catch (Exception e){
    24. clientStack.printStackTrace(); //若线程发生错误会在这里打印异常信息
    25. throw e;
    26. }
    27. };
    28. }
    29. }

    测试ThreadPoolExecutor

    1. public static void main(String[] args){
    2. ThreadPoolExecutor pe =
    3. new ThreadPoolExecutor(0, 10, 30L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
    4. // new TraceThreadPoolExecutor(0, 10,30L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
    5. for(int i=0 ; i<5 ; i++){
    6. // pe.submit(new MyTask(100, i));
    7. pe.execute(new MyTask(100, i));
    8. /* ThreadPoolExecutor.submit,不会打印任何错误信息
    9. * ThreadPoolExecutor.execute,打印线程异常信息
    10. * TraceThreadPoolExecutor.submit,只打印部分信息(哪里创建了异常线程)
    11. * TraceThreadPoolExecutor.execute,打印了全部异常信息(包括创建异常线程的位置,已经哪里发生了异常)
    12. */
    13. }
    14. pe.shutdown();
    15. }

    console

    1. Exception in thread "pool-1-thread-1" 100
    2. 50
    3. 33
    4. 25
    5. java.lang.ArithmeticException: / by zero
    6. at concurrent.C03_TraceThreadPoolExecutor$MyTask.run(C03_TraceThreadPoolExecutor.java:16)
    7. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    8. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    9. at java.lang.Thread.run(Thread.java:748)

    虽然控制台提示我们有错误,但是我们并不知道错误发生在什么地方,这不利于我们定位错误。


    测试TraceThreadPoolExecutor

    1. public static void main(String[] args){
    2. ThreadPoolExecutor pe =
    3. new TraceThreadPoolExecutor(0, 10,30L, TimeUnit.SECONDS, new LinkedBlockingDeque<>());
    4. for(int i=0 ; i<5 ; i++){
    5. // pe.submit(new MyTask(100, i));
    6. pe.execute(new MyTask(100, i));
    7. /* ThreadPoolExecutor.submit,不会打印任何错误信息
    8. * ThreadPoolExecutor.execute,打印线程异常信息
    9. * TraceThreadPoolExecutor.submit,只打印部分信息(哪里创建了异常线程)
    10. * TraceThreadPoolExecutor.execute,打印了全部异常信息(包括创建异常线程的位置,已经哪里发生了异常)
    11. */
    12. }
    13. pe.shutdown();
    14. }

    console

    1. java.lang.Exception: Client stack trace
    2. at concurrent.C03_TraceThreadPoolExecutor$TraceThreadPoolExecutor.clientTrace(C03_TraceThreadPoolExecutor.java:36)
    3. at concurrent.C03_TraceThreadPoolExecutor$TraceThreadPoolExecutor.execute(C03_TraceThreadPoolExecutor.java:27)
    4. at concurrent.C03_TraceThreadPoolExecutor.main(C03_TraceThreadPoolExecutor.java:63)
    5. Exception in thread "pool-1-thread-1" java.lang.ArithmeticException: / by zero
    6. at concurrent.C03_TraceThreadPoolExecutor$MyTask.run(C03_TraceThreadPoolExecutor.java:16)
    7. 100
    8. 50
    9. 33
    10. 25
    11. at concurrent.C03_TraceThreadPoolExecutor$TraceThreadPoolExecutor.lambda$0(C03_TraceThreadPoolExecutor.java:44)
    12. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    13. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    14. at java.lang.Thread.run(Thread.java:748)