Kaa*_*rde 10 java multithreading futuretask threadpool threadpoolexecutor
我想处理ThreadPoolExecutor#afterExecute()方法中工作线程抛出的exeptions .目前我有这个代码:
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..");
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我运行代码,我得到输出:
in call()
in afterExecute()
t == null
Run Code Online (Sandbox Code Playgroud)
为什么参数Throwable t null在afterExecute()?不应该是SQLException实例吗?
这实际上是预期的行为.
引用afterExecuteJavadoc:
如果为非null,则Throwable是未捕获的RuntimeException或Error,导致执行突然终止.
这意味着Throwable实例会RuntimeException或者Error,不检查Exception.由于SQLException是一个经过检查的异常,因此不会传递给它afterExecute.
这里还有其他东西(仍引用Javadoc):
注意:当操作被
FutureTask显式地或通过诸如submit之类的方法包含在任务(例如)中时,这些任务对象会捕获并维护计算异常,因此它们不会导致突然终止,并且内部异常不会传递给此方法.
在您的示例中,FutureTask由于您要提交a Callable,因此任务包含在a中,因此您就是这种情况.即使在你改变你的代码投掷RuntimeException,如果不会给afterExecute.Javadoc提供了一个示例代码来处理这个,我在这里复制,以供参考:
Run Code Online (Sandbox Code Playgroud)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); }