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 线程池中的异常处理的主要内容,如果未能解决你的问题,请参考以下文章

C# -Task.Run() 中线程池中的索引超出范围异常

京东二面:线程池中的线程抛出了异常,该如何处理?大部分人都会答错!

线程池中某个线程执行有异常,该如何处理?

线程池中某个线程执行有异常,该如何处理?

Java线程池中的四种拒绝策略

Java并发程序设计线程池之异常终止和正常关闭