Java多线程 处理子线程异常的两种策略.(UncaughtExceptionHandler的介绍)

方法一: 手动在每个run方法中进行try catch

如下的代码示例中, 就是在子线程中, 进行异常的捕获

package com.thread.uncaughtexception;

public class CantCatchDirectly implements Runnable{

    public static void main(String[] args) throws InterruptedException {
        //try {
            new Thread(new CantCatchDirectly(),"MyThread-1").start();

            Thread.sleep(300);

            new Thread(new CantCatchDirectly(),"MyThread-2").start();

            Thread.sleep(300);
            new Thread(new CantCatchDirectly(),"MyThread-3").start();

            Thread.sleep(300);

            new Thread(new CantCatchDirectly(),"MyThread-4").start();
        //} catch (RuntimeException e) {
        //    e.printStackTrace();
        //}
    }


    @Override
    public void run() {
        try {
            throw new RuntimeException();
        } catch (RuntimeException e) {
           // e.printStackTrace();
            System.out.println(" 捕获了异常 ");
        }
    }

}

打印如下

这样做的弊端就是在每一个run方法中, 都要去捕获异常, 并且还要判断其异常的类型, 这样做效率太低.

方法二: 使用UncaughtExceptionHandler

通过如下的源码可以看到UncaughtExceptionHandler接口为Thread类的内部接口, 并且只有一个方法.返回值为void .
参数为两个, 一个是线程 ,一个是异常. 代表是哪个线程 ,抛了哪个异常信息.

Java异常处理器的调用策略

异常处理器的源码如下:
主要的逻辑是:
首先检查是否有父线程, 如果有的话, 就用父线程的方法. 就是下面源码的parent.uncaughtException(t,e) 这个方法其实是本身, 就是递归调用. 会一直找到最顶层的ThreadGroup的异常处理器.

如果找到顶层的过程中,还是没有线程去处理, 那么就会进入到else的部分.
在else的部分, 会调用Thread.getDefaultUncaughtExceptionHandler.
如果没有实现UncaughtExceptionHandler这个接口, 那么获取的就是null ,则直接输出异常堆栈信息. 如果获取的不为空, 那么就会根据用户写的代码的实现, 去进行异常的处理 .

猜你喜欢

转载自blog.csdn.net/qq_33229669/article/details/108309844