Thread.UncaughtExceptionHandler类的作用:捕获并处理线程run方法抛出的异常。
Thread.UncaughtExceptionHandler exceptionHandler = (t, e) -> {
System.out.println("报错线程:" + t.getName());
System.out.println("线程抛出的异常:" + e);
};
Thread thread = new Thread(() -> {
throw new RuntimeException("throw a new Exception ! ");
});
thread.setUncaughtExceptionHandler(exceptionHandler); // 设置异常处理器
thread.start();
Thread.UncaughtExceptionHandler exceptionHandler = (t, e) -> {
System.out.println("报错线程:" + t.getName());
System.out.println("线程抛出的异常:" + e);
};
Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);
通过这种方式,后续的Thread都可以公用这个异常处理类。如果需要用其它方式处理异常时,只需要实现1中的内容即可。
// Thread.UncaughtExceptionHandler
@FunctionalInterface
public interface UncaughtExceptionHandler {
void uncaughtException(Thread t, Throwable e);
}
// 作用于当个Thread线程
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
// static修饰,其可以作用于所有Thread线程
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
// Thread#getUncaughtExceptionHandler
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
// ……
public void uncaughtException(Thread t, Throwable e) {
// 父级ThreadGroup的处理方法
if (parent != null) {
parent.uncaughtException(t, e);
} else {
// Thread 的全局默认处理方法
Thread.UncaughtExceptionHandler ueh =
Thread.getDefaultUncaughtExceptionHandler();
if (ueh != null) {
ueh.uncaughtException(t, e);
} else if (!(e instanceof ThreadDeath)) {
System.err.print("Exception in thread \""
+ t.getName() + "\" ");
e.printStackTrace(System.err);
}
}
}
// ……
}
要捕获ThreadPoolExecutor线程池中的线程执行异常,需要实现被protected修饰的方法afterExecute,在该方法里面处理异常即可。
// ThreadPoolExecutor#afterExecute
class ExtendedExecutor extends ThreadPoolExecutor {
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
// 如果Runnable是Future类型,那么异常将会直接通过Future返回
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
// 非Future类型
if (t != null)
System.out.println(t);
}
}
注意:实现afterExecute方法时,要正确嵌套多个覆盖,子类通常应在此方法的开头调用super.afterExecute,以确保不会破坏其他父类方法的实现。
// ThreadPoolExecutor#runWorker
final void runWorker(Worker w) {
Thread wt = Thread.currentThread();
Runnable task = w.firstTask; // 实际提交的任务
// …………
try {
beforeExecute(wt, task); // task执行前的操作
Throwable thrown = null; // 异常信息保存
try {
task.run(); // 执行任务
} catch (RuntimeException x) {
thrown = x; throw x;
} catch (Error x) {
thrown = x; throw x;
} catch (Throwable x) {
thrown = x; throw new Error(x);
} finally {
afterExecute(task, thrown); // task执行后的操作,也就包括了异常的捕获工作
}
} finally {
task = null;
w.completedTasks++;
w.unlock();
}
// ……
}
// ThreadPoolExecutor#afterExecute
protected void afterExecute(Runnable r, Throwable t) { }
// AbstractExecutorService#submit
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
// Callable任务会被封装成FutureTask
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
在FutureTask的run方法中,他们内部会将整个任务用try-catch给包起来。因此,也不会抛出Callable#run执行的内部异常。
// FutureTask#run
public void run() {
// ……
try {
Callable<V> c = callable;
// ……
// 这里将Callable的执行过程产生的异常都捕获了
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {
// ……