在开发过程中,异常不可避免的出现,对于捕获异常,通常这是在主线程中进行捕获,但是对于子线程发生的异常,主线程却无法通过try-catch捕获,因此需要使用UncaughtExceptionHandler
来进行全局捕获异常。
1、UncaughtExceptionHandler
首先看一段代码
public static void main(String[] args) {
try {
new Thread(new ThreadException(),"Thread-1").start();
new Thread(new ThreadException(),"Thread-2").start();
new Thread(new ThreadException(),"Thread-3").start();
}catch (RuntimeException e){
System.out.println("捕获到了异常");
}
}
@Override
public void run() {
//子线程抛出运行时异常
throw new RuntimeException();
}
按照我们自己的想法,在主线程使用try-catch代码块捕获异常,如果能够捕获到异常,那么就会打印catch代码块中的代码,但是并没有。
Exception in thread "Thread-1" Exception in thread "Thread-3" java.lang.RuntimeException
at thread_core.exception.ThreadException.run(ThreadException.java:22)
at java.base/java.lang.Thread.run(Thread.java:834)
Exception in thread "Thread-2" java.lang.RuntimeException
at thread_core.exception.ThreadException.run(ThreadException.java:22)
at java.base/java.lang.Thread.run(Thread.java:834)
java.lang.RuntimeException
at thread_core.exception.ThreadException.run(ThreadException.java:22)
at java.base/java.lang.Thread.run(Thread.java:834)
这是因为在子线程发生的异常,在主线程并没有被捕获到,所以这也是引出UncaughtExceptionHandler
的原因。
解决方式1(不推荐):在子线程中,try-catch异常处理。
@Override
public void run() {
try {
//子线程抛出运行时异常
throw new RuntimeException();
}catch (RuntimeException e){
System.out.println("捕获到了异常");
}
}
捕获到了异常
捕获到了异常
捕获到了异常
解决方式2:自定义异常捕获器UncaughtExceptionHandler
public class MyUncaughtExceptionHandler
implements Thread.UncaughtExceptionHandler {
private String msg;
public MyUncaughtExceptionHandler(String msg){
this.msg = msg;
}
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
Logger logger = Logger.getAnonymousLogger();
logger.log(Level.WARNING,"异常出现"+thread.getName());
System.out.println(msg+"捕获了"+thread.getName()+"的"+throwable+"异常");
}
}
public class UncaughtHandlerRunnable implements Runnable {
public static void main(String[] args) {
//设置全局异常捕获器
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler("捕获器1"));
new Thread(new UncaughtHandlerRunnable()).start();
new Thread(new UncaughtHandlerRunnable()).start();
new Thread(new UncaughtHandlerRunnable()).start();
}
@Override
public void run() {
throw new RuntimeException();
}
}
6月 04, 2020 10:34:59 上午 thread_core.exception.MyUncaughtExceptionHandler uncaughtException
警告: 异常出现Thread-2
6月 04, 2020 10:34:59 上午 thread_core.exception.MyUncaughtExceptionHandler uncaughtException
警告: 异常出现Thread-0
6月 04, 2020 10:34:59 上午 thread_core.exception.MyUncaughtExceptionHandler uncaughtException
警告: 异常出现Thread-1
捕获器1捕获了Thread-2的java.lang.RuntimeException异常
捕获器1捕获了Thread-1的java.lang.RuntimeException异常
捕获器1捕获了Thread-0的java.lang.RuntimeException异常
这样即便是在主线程,依然能够捕获全局出现的异常信息。