1、JAVA异常体系图
2、如何全局处理异常?为什么要全局处理?可不可以不处理?
线程的未捕获异常UncaughtExcption应该如何处理
1、为什么需要UncaughtExcptionHandler?
- 主线程可以轻松发现异常,子线程却不行
主线程往往会打印茫茫多的日志,子线程的异常信息可能埋没在其中没有被发现了,比如这段代码
public class ExceptionInChildThread implements Runnable{
public static void main(String[] args) {
new Thread(new ExceptionInChildThread()).start();
for (int i = 0; i < 10000; i++) {
System.out.println(i);
}
}
@Override
public void run() {
throw new RuntimeException();
}
}
如果不通过查找去看的话,很容易忽略掉子线程的异常

- 子线程异常无法用传统方式捕获(try-catch)
/**
* 1. 不加try catch抛出4个异常,都带线程名字
* 2. 加了try catch,期望捕获到第一个线程的异常,线程234不应该运行,希望看到打印出Caught Exception
* 3. 执行时发现,根本没有Caught Exception,线程234依然运行并且抛出异常
*
* 说明线程的异常不能用传统方法捕获
*/
public class NotCatchDirectly implements Runnable {
@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) throws Exception {
try {
new Thread(new NotCatchDirectly(), "MyThread-1").start();
Thread.sleep(300);
new Thread(new NotCatchDirectly(), "MyThread-2").start();
Thread.sleep(300);
new Thread(new NotCatchDirectly(), "MyThread-3").start();
Thread.sleep(300);
new Thread(new NotCatchDirectly(), "MyThread-4").start();
Thread.sleep(300);
} catch (RuntimeException e) {
System.out.printf("catch the exception");
}
}
}
并没有得到catch到异常,原因是catch只能捕获当前线程中的异常,在main中使用try-catch只会捕获main中产生的异常

- 不能直接捕获的后果、提高健壮性
两种解决方法
1、(不好)手动在每个run方法里面进行try-catch
2、(推荐)利用UncaughtExcptionHandler
- void uncaughtException(Thread t, Throwable e)
- 异常处理器的调用策略
- 自己实现
- 给程序统一设置;
- 给每个线程单独设置;
- 给线程池设置
handler类:
public class OwnExceptionHandler implements Thread.UncaughtExceptionHandler {
private String name;
public OwnExceptionHandler(String name) {
this.name = name;
}
@Override
public void uncaughtException(Thread t, Throwable e) {
Logger logger = Logger.getAnonymousLogger();
logger.log(Level.WARNING, "线程异常,终止" + t.getName());
logger.log(Level.INFO, name + "捕获了异常:" + t.getName() + "异常");
}
}
使用handler的主类
public class UseOwnHandler implements Runnable {
@Override
public void run() {
throw new RuntimeException();
}
public static void main(String[] args) throws InterruptedException {
Thread.setDefaultUncaughtExceptionHandler(new OwnExceptionHandler("自己的捕获器"));
new Thread(new UseOwnHandler(), "MyThread-1").start();
Thread.sleep(300);
new Thread(new UseOwnHandler(), "MyThread-2").start();
Thread.sleep(300);
new Thread(new UseOwnHandler(), "MyThread-3").start();
Thread.sleep(300);
new Thread(new UseOwnHandler(), "MyThread-4").start();
Thread.sleep(300);
}
}
结果如下,可以看出handler捕获到了子线程的异常并进行了处理。
