Java 线程异常处理

当多线程应用程序运行出现空指针异常,可以使用UncaughtExceptionHandler类进行捕捉,进而处理。

下面通过官方文档对UncaughtExceptionHandler进一步了解:
Java 线程异常处理
此类是Thread接口中的。
Java 线程异常处理
描述:
当线程由于未捕获的异常而即将终止时,Java虚拟机将查询线程的 UncaughtExceptionHandler使用情况 Thread.getUncaughtExceptionHandler(),并将调用处理程序的 uncaughtException方法,将线程和异常作为参数传递。如果一个线程没有UncaughtExceptionHandler 明确设置,那么它的ThreadGroup对象就像它一样 UncaughtExceptionHandler。
如果ThreadGroup对象没有处理异常的特殊要求,它可以将调用转发给默认的未捕获异常处理程序。

该类的方法:
Java 线程异常处理
可以使用如下方法对线程设置默认的异常处理器:

Thread.setDefaultUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)——>public static void setDefaultUncaughtExceptionHandler​(Thread.UncaughtExceptionHandler eh)
eh - 用作默认未捕获异常处理程序的对象。如果null那时没有默认处理程序。

设置当线程由于未捕获的异常而突然终止时调用的默认处理程序,并且没有为该线程定义其他处理程序。未捕获的异常处理首先由线程控制,然后由线程的ThreadGroup对象控制,最后由默认的未捕获异常处理程序控制。如果线程没有明确的未捕获异常处理程序集,并且线程的线程组(包括父线程组)不专门化其 uncaughtException方法,则将uncaughtException调用默认处理程序的 方法。

通过设置默认的未捕获异常处理程序,应用程序可以更改已经接受系统提供的任何“默认”行为的线程处理未捕获异常的方式(例如,记录到特定设备或文件)。

请注意,默认的未捕获异常处理程序通常不应该遵循线程的ThreadGroup对象,因为这可能导致无限递归。

Thread.setUncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler)——>public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
eh - 用作此线程的未捕获异常处理程序的对象。如果null那么这个线程没有显式处理程序。

设置当此线程由于未捕获的异常而突然终止时调用的处理程序。
线程可以通过显式设置未捕获的异常处理程序来完全控制它如何响应未捕获的异常。如果没有设置这样的处理程序,则线程的ThreadGroup 对象充当其处理程序。

ThreadGroup.uncaughtException(java.lang.Thread, java.lang.Throwable)——>public void uncaughtException(Thread t, Throwable e)
t - 即将退出的线程。
e - 未被捕获的例外。

当此线程组中的线程因未捕获的异常而停止并且该线程未Thread.UncaughtExceptionHandler 安装特定时,由Java虚拟机调用。
该uncaughtException方法 ThreadGroup执行以下操作:

如果此线程组具有父线程组,uncaughtException则使用相同的两个参数调用该父线程的 方法。
否则,此方法将检查是否安装了 默认的未捕获异常处理程序,如果是,uncaughtException则使用相同的两个参数调用其 方法。
否则,此方法确定Throwable 参数是否是实例ThreadDeath。如果是这样,没有什么特别的。否则,包含该线程的名称的消息,如从线程的返回getName的方法,以及在堆栈中,使用Throwable的printStackTrace方法中,被打印到标准错误流。
应用程序可以在子类中覆盖此方法, ThreadGroup以提供对未捕获异常的替代处理。

下面通过代码来 操练 此类异常:

Java 线程异常处理
Java 线程异常处理
如果想操练其他的方法,改下方法就行了,这里不做操练演示。
线程组也是同样道理,不过需要注意:
使用自定义java.lang.ThreadGroup线程组,并重写uncaughtException方法处理组内线程中断行为时,每个线程对象中的run()方法内部不要出现有异常catch语块。如果出现,uncaughtException方法会不执行。
对于多个线程,如果要处理多个异常,也可以放在一起进行运行处理。

线程异常处理的传递:
Java 线程异常处理
Java 线程异常处理
Java 线程异常处理
Java 线程异常处理
输出结果:
Java 线程异常处理
修改如下代码:
Java 线程异常处理
Java 线程异常处理
还是对象的异常处理,如果把处理对象异常处理的线程注释掉,则输出的是静态的异常处理和线程组异常,如果注释掉两个线程异常处理,则抛出线程组异常处理的信息。