当一个线程在执行过程中抛出了异样,并且没有进行try..catch,那么这个线程就会终止运行。
在Thread类中,提供了两个能够设置线程未捕捉异样的全局处理器,咱们能够在处理器里做一些工作,例如将异样信息发送到近程服务器。
尽管这能够捕捉到线程中的异样,然而并不能阻止线程进行运行。因而该在线程run办法里try..catch的,还是要好好的进行try..catch。

从Thread类源代码中能够看到这2个变量:

private volatile UncaughtExceptionHandler uncaughtExceptionHandler;private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;

须要留神到区别,defaultUncaughtExceptionHandler是动态的,咱们能够调用此办法设置所有线程对象的异样处理器,而uncaughtExceptionHandler则是针对单个线程对象的异样处理器。

uncaughtExceptionHandler优先级高于defaultUncaughtExceptionHandler。

Thread类提供了这2个变量的setter/getter:

public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {    SecurityManager sm = System.getSecurityManager();    if (sm != null) {        sm.checkPermission(            new RuntimePermission("setDefaultUncaughtExceptionHandler")          );    }     defaultUncaughtExceptionHandler = eh; }    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){    return defaultUncaughtExceptionHandler;}public UncaughtExceptionHandler getUncaughtExceptionHandler() {    return uncaughtExceptionHandler != null ?        uncaughtExceptionHandler : group;}public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {    checkAccess();    uncaughtExceptionHandler = eh;}

能够看到,getUncaughtExceptionHandler()中进行了判断,当uncaughtExceptionHandler为null时返回group。

咱们来看下UncaughtExceptionHandler接口是怎么申明的:

@FunctionalInterfacepublic interface UncaughtExceptionHandler {    void uncaughtException(Thread t, Throwable e);}

咱们只须要实现UncaughtExceptionHandler接口,重写uncaughtException办法即可进行异样解决。

那么JVM是怎么检测到线程产生异样,并将异样散发到处理器的呢?
对于这块代码,JDK源码中看不到是如何解决的,可能须要翻阅hotspot源码,不过Thread类中提供了一个dispatchUncaughtException办法,将异样回调到了uncaughtExceptionHandler中去解决。

private void dispatchUncaughtException(Throwable e) {    getUncaughtExceptionHandler().uncaughtException(this, e);}

很显著,dispatchUncaughtException应该就是提供给hotspot进行JNI回调的。
而对于defaultUncaughtExceptionHandler的调用,猜想应该是在hotspot中间接实现了。

接下来咱们用示例来演示一下异样处理器的成果。

示例:

Thread thread = new Thread(() -> {    System.out.println("run before");    System.out.println("runing");    if(1 == 1) {        throw new IllegalStateException("exception");    }    System.out.println("run after");});thread.setUncaughtExceptionHandler((t, e) -> System.out.println("捕捉异样," + t.getName() + "," + e.getMessage()));Thread.setDefaultUncaughtExceptionHandler((t, e) -> System.out.println("Default捕捉异样," + t.getName() + "," + e.getMessage()));thread.start();

输入:

run beforeruning捕捉异样,Thread-0,exception

能够看出,尽管两个异样处理器都有设置,并且defaultUncaughtExceptionHandler是最初设置的,不过起效的是uncaughtExceptionHandler。

能够将thread.setUncaughtExceptionHandler(...);正文掉:
输入:

run beforeruningDefault捕捉异样,Thread-0,exception

正文后,defaultUncaughtExceptionHandler起效了,证实了uncaughtExceptionHandler优先级高于defaultUncaughtExceptionHandler。