捕获其他线程的异常UncaughtExceptionHandler
在A线程里起了另B线程,但B线程报错了,这时想要在A线程里捕获B线程的异常是无法做的,除非在捕获B线程前先设置线程捕获器。直接来看代码:
package com.wulf.exceptionHandler; import java.lang.Thread.UncaughtExceptionHandler; public class ExceptionCatcher { public static void main(String[] args) { // 1、新线程抛异常,main线程无法捕获 try { new Thread() { @Override public void run() { System.out.println("第一个空指针来了:"); throw new NullPointerException(); } }.start(); } catch (Exception e) { System.out.println("第一次抛出异常!"); } // 2、通过线程捕获异常 try { // 先休眠,等上面的线程自动结束 Thread.sleep(1000); // 先设置捕获线程 Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.printf("线程:%s 抛出异常:%s\n", t.getName(), e.getClass().getName()); e.printStackTrace(); } }); // 新起线程抛出异常 new Thread() { @Override public void run() { System.out.println("第二个空指针来了:"); throw new NullPointerException(); } }.start(); } catch ( Exception e) { System.out.println("第二次抛出异常!"); } } }
运行结果:
第一个空指针来了: Exception in thread "Thread-0" java.lang.NullPointerException at com.wulf.exceptionHandler.ExceptionCatcher$1.run(ExceptionCatcher.java:16) at java.lang.Thread.run(Thread.java:745) 第二个空指针来了: 线程:Thread-1 抛出异常:java.lang.NullPointerException java.lang.NullPointerException at com.wulf.exceptionHandler.ExceptionCatcher$3.run(ExceptionCatcher.java:46) at java.lang.Thread.run(Thread.java:745)
根据线程执行速度不同,新起的线程里exception和本地线程里字符串的打印顺序先后有可能不同。看下的UncaughtExceptionHandler的源码:
/** * Interface for handlers invoked when a <tt>Thread</tt> abruptly * terminates due to an uncaught exception. * <p>When a thread is about to terminate due to an uncaught exception * the Java Virtual Machine will query the thread for its * <tt>UncaughtExceptionHandler</tt> using * {@link #getUncaughtExceptionHandler} and will invoke the handler's * <tt>uncaughtException</tt> method, passing the thread and the * exception as arguments. * If a thread has not had its <tt>UncaughtExceptionHandler</tt> * explicitly set, then its <tt>ThreadGroup</tt> object acts as its * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object * has no * special requirements for dealing with the exception, it can forward * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler * default uncaught exception handler}. * * @see #setDefaultUncaughtExceptionHandler * @see #setUncaughtExceptionHandler * @see ThreadGroup#uncaughtException * @since 1.5 */ @FunctionalInterface public interface UncaughtExceptionHandler { /** * Method invoked when the given thread terminates due to the * given uncaught exception. * <p>Any exception thrown by this method will be ignored by the * Java Virtual Machine. * @param t the thread * @param e the exception */ void uncaughtException(Thread t, Throwable e); }
上面的注释告诉我们线程查找未捕获异常的顺序:Thread实例的setUncaughtExceptionHandler -> ThreadGroup的setUncaughtExceptionHandler ->
Thread的静态方法Thread.setDefaultUncaughtExceptionHandler。我们把例子改一下:
public class Test { public static void main(String[] args) { // 1、新线程抛异常,main线程无法捕获 try { new Thread() { @Override public void run() { System.out.println("第一个空指针来了:"); throw new NullPointerException(); } }.start(); } catch (Exception e) { System.out.println("第一次抛出异常!"); } // 2、通过线程捕获异常 try { // 先休眠,等上面的线程自动结束 Thread.sleep(1000); // 先设置捕获线程 Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { System.out.printf("[setDefaultUncaughtExceptionHandler] 线程:%s 抛出异常:%s\n", t.getName(), e.getClass().getName()); e.printStackTrace(); } }); // 新起线程抛出异常 Thread thread = new Thread() { @Override public void run() { System.out.println("第二个空指针来了:"); throw new NullPointerException(); } }; thread.setUncaughtExceptionHandler((Thread t, Throwable e) -> { System.out.printf("[setUncaughtExceptionHandler] 线程:%s 抛出异常:%s\n", t.getName(), e.getClass().getName()); e.printStackTrace(); }); thread.start(); } catch ( Exception e) { System.out.println("第二次抛出异常!"); } } }
运行结果:
第一个空指针来了: Exception in thread "Thread-0" java.lang.NullPointerException at com.wlf.springcloudgateway.Test$1.run(Test.java:33) 第二个空指针来了: [setDefaultUncaughtExceptionHandler] 线程:Thread-1 抛出异常:java.lang.NullPointerException java.lang.NullPointerException at com.wlf.springcloudgateway.Test$3.run(Test.java:62)
浙公网安备 33010602011771号