回答
通常情况下,线程池中的线程在执行过程中出现了未捕获的异常时,线程会立刻终止,线程池是不会将异常抛给使用者的。如果我们不加以处理,则可能会导致一些问题,如资源未释放,错误难以诊断等等,所以为了我们系统的健壮性和可维护性,我们一般都需要对异常进行处理,方式有如下几种:
- 使用
try-catch
块:在任务中直接使用try-catch
来捕获和处理异常,这是最直接的方式。 UncaughtExceptionHandler
:实现 ThreadFactory 接口,我们可以创建一个自定义的线程工厂,在这个工厂里,我们创建自定义的线程,并为这些线程设置一个UncaughtExceptionHandler
。该处理器会捕获线程执行过程中未被捕获的异常。- 使用
submit()
返回Future
对象:使用ExecutorService.submit()
提交任务,该方法会返回一个Future
对象。我们可以通过Future.get()
方法,获取线程在执行过程中的任何异常。这些异常会被封装在ExecutionException
中。 - 重写
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);
}
}
}