2024-03-23
版权声明:本文为博主付费文章,严禁任何形式的转载和摘抄,维权必究。 本文链接:https://www.skjava.com/mianshi/baodian/detail/6568512032

回答

通常情况下,线程池中的线程在执行过程中出现了未捕获的异常时,线程会立刻终止,线程池是不会将异常抛给使用者的。如果我们不加以处理,则可能会导致一些问题,如资源未释放,错误难以诊断等等,所以为了我们系统的健壮性和可维护性,我们一般都需要对异常进行处理,方式有如下几种:

  1. 使用 try-catch 块:在任务中直接使用 try-catch 来捕获和处理异常,这是最直接的方式。
  2. UncaughtExceptionHandler:实现 ThreadFactory 接口,我们可以创建一个自定义的线程工厂,在这个工厂里,我们创建自定义的线程,并为这些线程设置一个 UncaughtExceptionHandler。该处理器会捕获线程执行过程中未被捕获的异常。
  3. 使用 submit()返回 Future 对象:使用 ExecutorService.submit() 提交任务,该方法会返回一个 Future 对象。我们可以通过 Future.get() 方法,获取线程在执行过程中的任何异常。这些异常会被封装在ExecutionException 中。
  4. 重写 afterExecute() 方法:重写 afterExecute(),该方法在每个任务执行完成后都会被调用,无论任务是正常完成还是异常终止,在该方法中我们就可以获取线程执行过程中的异常信息。

详解

模拟线程池抛异常

我们定义要给线程,内部抛出异常:

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " - 进入 run(),开始执行任务");

        int i = 1 / 0;
    }
}

写个测试类:

public class ThreadPoolException {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        executorService.submit(new MyRunnable());
        executorService.execute(new MyRunnable());
    }
}

执行结果:

对于这种异常信息的处理,我们有多种方法。

1、使用 try-catch 块

在任务中直接使用 try-catch 块来捕获并处理这些异常,这是一种最简单方式:

public class MyRunnable implements Runnable{
    @Override
    public void run() {
        try {
            System.out.println(Thread.currentThread().getName() + " - 进入 run(),开始执行任务");

            int i = 1 / 0;
        } catch (Exception e) {
            System.out.println(Thread.currentThread().getName() + " - 捕获异常信息" + e);
        }
    }
}