多线程异常捕获与处理
线程与异常
每一个Java应用程序都是一个进程,在进程中会启动多个线程来执行各类任务。因为Java线程的本质,所以当在一个Java的线程中抛出异常的时候,需要在当前线程中catch并处理。如果当前线程没有catch住这个异常,那么这个异常就会被抛出,并导致这个线程运行终止。因此对于Java的线程异常处理只能由当前线程来处理,其他线程是无法感知的。
处理方式
- 基于内部try,catch的方式
public void run(){
try{
}catch(Throwable e){
backgroundException = e;
}
}
在主线程,或者其他线程判断对应的backgroundException是否为null,如果不为null表示上次线程执行过程中出现了异常,然后执行异常处理逻辑。
- 基于异常处理器的方法
在Java中有一个异常处理器uncaughtExceptionHandler的接口,并且每一个线性对象Thread都有一个属性:uncaughtExceptionHandler。如果一个线程内部产生了异常,并且没有try,catch来处理,最终会被uncaughtExceptionHandler这个对象捕获。如果uncaughtExceptionHandler这个对象为null的话,这个异常就无法被捕获。
示例:
实现UncaughtExceptionHandler接口
public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
@Override
publicvoid uncaughtException(Thread t, Throwable e) {
System.out.println("捕获到异常:"+e);
//TODO处理异常的逻辑
}
}
设置线程对象的uncaughtExceptionHandler
Thread thread = new Thread();
MyUncaughtExceptionHandler exceptionHandler = new MyUncaughtExceptionHandler();
thread.setUncaughtExceptionHandler(exceptionHandler);
线程池中使用的问题(正在仔细研究线程池的底层实现)
在实践中我们常常使用线程池来管理线程任务。通常提交任务的方式有两种(除了定时任务外)execute,submit(有future返回值)。
如果希望线程在执行出现异常的时候,使用方法2的方式来捕获异常,就需要实现自己的ThreadFactory,为每一个Thread对象都设置异常处理器uncaughtExceptionHandler。但是这种方法只有在以execute提交任务的时候才有效。
对于submit提交的任务,会有一个future返回值,可以通过future的get方法获得最终线程的执行结果或者异常。