当一个线程在执行过程中抛出异常,没有try..catch,那么这个线程就会终止。在Thread类中,提供了两个可以设置线程未捕获异常的全局处理器。我们可以在处理器中做一些工作,比如向远程服务器发送异常信息。虽然这会捕获线程中的异常,但不会阻止线程停止。所以需要在线程run方法中try..catch,或者try..catch很好。从Thread类源码中可以看到这两个变量:privatevolatileUncaughtExceptionHandleruncaughtExceptionHandler;privatestaticvolatileUncaughtExceptionHandlerdefaultUncaughtExceptionHandler;需要注意区别,defaultUncaughtExceptionHandler是静态的,我们可以调用该方法为所有线程对象设置异常处理器,而uncaughtExceptionHandler是为单个线程对象设置异常处理器。uncaughtExceptionHandler的优先级高于defaultUncaughtExceptionHandler。Thread类为这两个变量提供了setter/getter:publicstaticvoidsetDefaultUncaughtExceptionHandler(UncaughtExceptionHandlereh){if(sm!=null){sm.checkPermission(newRuntimePermission("setDefaulttionHandlerEx"p));}defaultUncaughtExceptionHandler=呃;}publicstaticUncaughtExceptionHandlergetDefaultUncaughtExceptionHandler(){returndefaultUncaughtExceptionHandler;}publicUncaughtExceptionHandlergetUncaughtExceptionHandler(){returnuncaughtExceptionHandler!=null?uncaughtExceptionHandler:group;}publicvoidsetUncaughtExceptionHandler(UncaughtExceptionHandlereh){checkAccess();uncaughtExceptionHandler=eh;}可以看出在getUncaughtExceptionHandler()中进行了判断,当uncaughtExceptionHandler为null时返回组。我们看看UncaughtExceptionHandler接口是如何声明的:@FunctionalInterfacepublicinterfaceUncaughtExceptionHandler{voiduncaughtException(Threadt,Throwablee);}我们只需要实现UncaughtExceptionHandler接口,重写uncaughtException方法来处理异常。那么JVM是如何检测到线程发生异常并将异常分发给处理器的呢?对于这段代码,在JDK源码中看不到是怎么处理的。可能需要阅读热点源码,Thread类提供了一个dispatchUncaughtException方法,将异常回调到uncaughtExceptionHandler处理。privatevoiddispatchUncaughtException(Throwablee){getUncaughtExceptionHandler().uncaughtException(this,e);}很明显,应该给热点提供dispatchUncaughtException,用于JNI回调。至于defaultUncaughtExceptionHandler的调用,猜测应该是直接在hotspot中进行的。下面我们用一个例子来演示一下异常处理器的作用。例子:Threadthread=newThread(()->{System.out.println("runbefore");System.out.println("runing");if(1==1){thrownewIllegalStateException("exception");}System.out.println("runafter");});thread.setUncaughtExceptionHandler((t,e)->System.out.println("捕捉异常,"+t.getName()+","+e.getMessage()));Thread.setDefaultUncaughtExceptionHandler((t,e)->System.out.println("默认捕获异常,"+t.getName()+","+e.getMessage()));thread.start();输出:runbeforeuningcatchesexception,Thread-0,exception可见,虽然两个异常处理器都设置了,defaultUncaughtExceptionHandler是最后设置的,但是effective是uncaughtExceptionHandler。Thread.setUncaughtExceptionHandler(...);可以注释掉:output:runbeforeuningDefaultcapturesexception,thread-0之后,exception被注释掉,defaultUncaughtExceptionHandler起作用,证明uncaughtExceptionHandler的优先级高于defaultUncaughtExceptionHandler。
