我的原则:先会用再说,内部慢慢来。
学以致用,根据场景学源码
一、前言
1.1 架构
- java.lang.Thread.UncaughtExceptionHandler
1.2 Class 架构
public class Thread implements Runnable {
@FunctionalInterface
public interface UncaughtExceptionHandler {
void uncaughtException(Thread t, Throwable e);
}
}
1.3 能干嘛?
- 捕获子线程抛出的异常
二、实战 demo
2.1 实战一:测试 Exception 逃逸
- 代码
public class _01_TestMultiThreadException {
// 现象:控制台打印出异常信息,并运行一段时间后才停止
public static void main(String[] args) {
// 就算把线程的执行语句放到 try-catch 块中也无济于事
try {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(() -> {
throw new RuntimeException("自定义的一个RuntimeException");
});
exec.shutdown();
} catch (Exception e) {
System.out.println("Exception has been handled!");
}
}
}
-
解析:上方的 try-catch 压根没法捕获到子线程抛出的 Exception
-
结论:
- 多线程运行不能按照顺序执行过程中捕获异常的方式来处理异常, 异常会被直接抛出到控制台。
- 由于线程的本质,使得你不能捕获从线程中逃逸的异常。一旦异常逃逸出任务的run方法,它就会向外传播到控制台,除非你采用特殊的形式捕获这种异常。
2.2 实战二:自定义 UncaughtExceptionHandler
- 步骤一:定义“异常处理器” UncaughtExceptionHandler
class MyUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler {
/*
Thread.UncaughtExceptionHandle.uncaughtException()
会在线程因未捕获的异常而临近死亡时被调用
*/
@Override
public void uncaughtException(Thread t, Throwable e) {
// 这里可以写 if else 处理各种各样的异常
if(e instanceof RuntimeException){
System.out.println("### MyUncaughtExceptionHandler catch " + e);
}
}
}
- 步骤二:定义线程工厂 ThreadFactory
- 工厂就是用来产生线程的,并给生成的线程绑定一个异常处理器。