zoukankan      html  css  js  c++  java
  • 捕获子线程中的异常

    如下代码,在 main 线程中,是无法捕获子线程的异常的。
    catch 子句中的代码不会被执行。

    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    public class NaiveExceptionHandling {
        public static void main(String[] args) {
            ExecutorService exec = Executors.newCachedThreadPool();
            try {
                exec.execute(() -> {
                    throw new RuntimeException();
                });
            } catch (RuntimeException e) {
                System.out.println("this msg will not de printed");
            }
            exec.shutdown();
        }
    }
    

    输出:

    Exception in thread "pool-1-thread-1" java.lang.RuntimeException
    	at NaiveExceptionHandling.lambda$main$0(NaiveExceptionHandling.java:9)
    	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)
    
    Process finished with exit code 0
    

    改造:

    • newCachedThreadPool 创建线程池时指定自定义的 ThreadFactory
    • 自定义的 ThreadFactory 工厂在生产线程时,为其设置 UncaughtExceptionHandler 异常处理
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ThreadFactory;
    
    public class NaiveExceptionHandling {
    
        public static void main(String[] args) {
            ExecutorService exec2 = Executors.newCachedThreadPool(new HandleThreadFactory());
            exec2.execute(() -> {
                throw new RuntimeException();
            });
            exec2.shutdown();
        }
    }
    
    class HandleThreadFactory implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            System.out.println("create thread t");
            Thread t = new Thread(r);
            System.out.println("set uncaughtException for t");
            t.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    System.out.println("caught " + e);
                }
            });
            return t;
        }
    
    }
    

    输出:

    create thread t
    set uncaughtException for t
    caught java.lang.RuntimeException
    

    那么主线程为什么不能捕获子线程的异常呢?知乎上有如下解释:

    • 因为execute方法会立即返回,所以早就运行出try块了,实际上主线程已经提前结束。
    • 设计的主要初衷是线程运行是互相独立的,可以理解主线程也是一种普通的线程即可。如果线程之间异常互相干扰,那么1000个线程,一个线程挂了,其它线程跟着遭殃,这是不合理的。

    ref:

    1. https://blog.csdn.net/wild46cat/article/details/80808555
    2. 《Java 编程思想(第4版)》 P672
    3. https://www.zhihu.com/question/67790293
  • 相关阅读:
    三点求圆心坐标(三角形外心)
    半平面交
    旋转卡壳
    平面最近点对(HDU 1007)
    凸包
    ACM做题随做随思
    最短路径——SPFA算法
    树链剖分原理
    生成树的计数——Matrix-Tree定理
    次小生成树
  • 原文地址:https://www.cnblogs.com/duanguyuan/p/13196770.html
Copyright © 2011-2022 走看看