在我给自定义ThreadPoolExecutor的Runnable任务中,我捕获了任何Throwable。然后我抛出一个自定义的RuntimeException而不是抛出相同的Exception。我在执行程序中覆盖了afterExecute(Runnable runnable,Throwable throwable)方法,并且正如预期的那样,执行后我可以使用该异常。我的理解是,除了这个例外之外什么都不应该发生,因为我已经注意处理它。但是,间歇性地允许异常进入主线程,然后使用Thread.getUncaughtExceptionHandler()将其打印到System.err。我已通过将以下内容放入我的应用程序的主要方法中来验证这一点:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.err.println("I shouldn't have got here!");
}
});
现在我可以轻松地在上面的代码中做任何事情,并阻止输出到System.err,但我想弄清楚为什么ThreadPoolExecutor让异常从我给它的任务中逃脱。有关为什么会发生这种情况的任何想法?
答案 0 :(得分:1)
ThreadPoolExecutor从任务中捕获并重新抛出异常:
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);
}
因此异常将由默认处理程序处理。
如果你想避免调用默认处理程序,那么你可以用RunTable包装FutureTask来维护异常,或者创建自己的包装器以便能够在适当的地方处理异常。
答案 1 :(得分:0)
如果您正在使用具有有界队列和CallerRunsPolicy
拒绝策略的TPE,那么runnable将在提交线程上执行,而不会有任何异常包装。
无论如何,这种情况应该从异常堆栈中显而易见。