一 体系化深入学习并发编程由简入繁系统梳理并发知识点(11)


一  体系化深入学习并发编程由简入繁系统梳理并发知识点

文章插图
线程的未捕获异常 为什么需要未捕获异常处理器
类提供了一个未捕获线程处理器的接口,用于处理未捕获线程,但是我们为什么需要这个未捕获线程处理器呢?它和普通的异常捕获有什么区别呢?
forwhen adue to an.
When ais about todue to anthe Javawill query thefor its dler using .() and willthe ’s,theand theas . If ahas not had its dlerset, then itsacts as its dler. If thehas noforwith the , it cantheto the.
子线程更难发现异常
在单线程程序中,如果遇到了未捕获异常,会自动抛出异常并打印堆栈信息,程序终止
比如如下代码:
public static void main(String[] args) {new Thread(()->{throw new RuntimeException("子线程发生了异常");}).start();for (int i = 0; i <1000; i++) {System.out.println("保存日志信息");}}
主线程在保存1000条日志信息,而在此期间子线程发生异常
...保存日志信息保存日志信息保存日志信息Exception in thread "Thread-0" java.lang.RuntimeException: 子线程发生了异常at uncaughtexception.UnCaughtExceptionInSubThread.lambda$main$0(UnCaughtExceptionInSubThread.java:9)at java.lang.Thread.run(Thread.java:748)保存日志信息保存日志信息...
子线程的异常,并不会导致主线程的停止,主线程依旧执行任务,而如果数据量更大,我们就更难寻找到这条异常信息了
普通的捕获异常并不能捕获子线程
public static void main(String[] args) {try {new Thread(()->{throw new RuntimeException("子线程异常");}).start();System.out.println("如果捕获到,这句话不会执行");}catch (RuntimeException e){System.out.println("捕获到了子线程异常");}}
可以看到,并没有捕获到子线程内部发生的异常,也就是主线程并没有感知到有异常发生,依旧正常运行
如果捕获到,这句话不会执行Exception in thread "Thread-0" java.lang.RuntimeException: 子线程异常at uncaughtexception.TryCatchSubThreadException.lambda$main$0(TryCatchSubThreadException.java:10)at java.lang.Thread.run(Thread.java:748)
因为主线程中的try/catch代码块只能捕获主线程的异常
处理子线程的异常 简单可用:在子线程内部使用try/catch
既然我子线程内部出现异常,那我在子线程内就对异常进行处理不就行了吗
将上面创建线程的语句修改一下:
new Thread(()->{try {throw new RuntimeException("子线程异常");}catch (RuntimeException e){System.out.println("在子线程内部捕获到了异常");}}).start();
这样就能正常捕获到子线程的异常
但是这样做有一个弊端,每个run方法都需要捕获异常,还需要知道异常的类型,导致代码更加繁琐
使用dler
这是一个函数式接口,只有一个方法
void ( t,e);
Java中类实现了该接口,是默认的异常处理器
这是实现后的方法
public void uncaughtException(Thread t, Throwable e) {//默认情况下parent为空,不过不为空,就调用父类的该方法if (parent != null) {parent.uncaughtException(t, e);} else {//否则调用全局异常处理器Thread.UncaughtExceptionHandler ueh =Thread.getDefaultUncaughtExceptionHandler();if (ueh != null) {ueh.uncaughtException(t, e);} else if (!(e instanceof ThreadDeath)) {//全局异常处理器也不存在,就打印堆栈信息System.err.print("Exception in thread \""+ t.getName() + "\" ");e.printStackTrace(System.err);}}}