我想在 ThreadPoolExecutor#afterExecute()
方法中处理工作线程抛出的异常。目前我有这段代码:
public class MyExecutor extends ThreadPoolExecutor {
public static void main(String[] args) {
MyExecutor threadPool = new MyExecutor();
Task<Object> task = new Task<>();
threadPool.submit(task);
}
public MyExecutor() {
super(4, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>(4000));
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
System.out.println("in afterExecute()");
if (t != null) {
System.out.println("exception thrown: " + t.getMessage());
} else {
System.out.println("t == null");
}
}
private static class Task<V> implements Callable<V> {
@Override
public V call() throws Exception {
System.out.println("in call()");
throw new SQLException("testing..");
}
}
}
如果我运行代码,我会得到输出:
in call()
in afterExecute()
t == null
为什么afterExecute()
中的参数Throwable t
null
?它不应该是 SQLException
实例吗?
最佳答案
这实际上是预期的行为。
引用 afterExecute
Java文档:
If non-null, the Throwable is the uncaught RuntimeException or Error that caused execution to terminate abruptly.
这意味着可抛出的实例将是RuntimeException
或Error
,不检查Exception
。由于 SQLException
是一个已检查的异常,它不会传递给 afterExecute
。
这里还有其他事情(仍然引用 Javadoc):
Note: When actions are enclosed in tasks (such as
FutureTask
) either explicitly or via methods such as submit, these task objects catch and maintain computational exceptions, and so they do not cause abrupt termination, and the internal exceptions are not passed to this method.
在您的示例中,任务包含在 FutureTask
中,因为您提交的是 Callable
,所以您属于这种情况。即使在您更改代码以抛出 RuntimeException
时,如果不会将其提供给 afterExecute
。 Javadoc 给出了一个示例代码来处理这个问题,我将其复制在这里,以供引用:
protected void afterExecute(Runnable r, Throwable t) { super.afterExecute(r, t); 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 } } if (t != null) System.out.println(t); }
关于java - 为什么 ThreadPoolExecutor 的 afterExecute() 异常为 null?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33758650/