20210601 线程池中的异常处理
Posted 陈如水
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20210601 线程池中的异常处理相关的知识,希望对你有一定的参考价值。
线程池异常处理
1,Runnable接口的run方法的完整签名,没有标识throws语句,所以方法是不会抛出checked异常的。至于RuntimeException这样的unchecked异常,由于新线程由JVM进行调度执行,如果发生了异常,也不会通知到父线程。
即:子线程中发生了异常,如果没有任何类来接手处理的话,是会直接退出的,虚拟机直接杀死线程,而不会记录任何日志。所以,如果什么都不做的话,是会出现子线程任务既没执行成功,也没有任何日志提示的“诡异”现象的。
java线程中,如果抛出未被捕获的异常,会导致线程终止。
2,一旦一个线程抛出了非受检异常,JVM就会把它杀死,然后把捕获到的非受检异常传递给UncaughtExceptionHandler类对象类处理.
3,当一个线程由于发生了非受检异常而终止时,JVM会使用Thread.gerUncaughtExceptionHandler()方法查看该线程上的UncaughtExceptionHandler,并调用他的uncaughtException()方法。
4,在使用线程池的时候,自己设置异常处理,获取线程的异常信息。
在父线程中启动了子线程,捕获子线程中的异常,从而进行相应的处理。
方法一,在子线程的执行方法中,将整个任务try-catch起来,捕获里面的异常。
方法二: 每一个任务都加一个try-catch 实在是太麻烦了,而且代码也不好看,那么这样想的话,可以用UncaughtExceptionHandler 这个类。
UncaughtExceptionHandler 是Thread类一个内部类,也是一个函数式接口。内部的uncaughtException是一个处理线程内发生的异常的方法,参数为线程对象t和异常对象e。
如果我们不想在每个线程的任务里面都加try-catch的话,可以自己实现的一个线程池,重写它的线程工厂方法,在创建线程的时候,都赋予UncaughtExceptionHandler处理器对象。
private static ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("thread-pool-%d")
.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
//子线程抛出异常
log.info("子线程执行异常,线程名:{},异常信息:{}", t.getName(), e.getMessage());
}
})
.build();
setDefaultUncaughtExceptionHandler的原理
Thread类里面dispatchUncaughtException(Throwable e) 这个方法,调用了 getUncaughtExceptionHandler().uncaughtException(this, e); 获取到了我们设置的UncaughtExceptionHandler,并把线程对象和异常对象都作为参数传进去了。这个方法,只能被JVM调用,将未捕获异常分派给该方法所在的处理程序调用的节点,就是当Thread对象抛出了未被捕获的异常的时候。
以上是关于20210601 线程池中的异常处理的主要内容,如果未能解决你的问题,请参考以下文章