我想处理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

为什么参数Throwable t nullafterExecute()中?不应该是SQLException实例吗?

最佳答案

这实际上是预期的行为。

引用 afterExecute Javadoc:



这意味着throwable实例将是RuntimeExceptionError,而不是选中的Exception。由于SQLException是一个已检查的异常,因此不会将其传递给afterExecute

这里还有其他事情(仍然引用Javadoc):



在您的示例中,由于您要提交FutureTask,因此该任务包含在Callable中,因此就是这种情况。即使在您更改代码以抛出RuntimeException的情况下,如果不将其提供给afterExecute。 Javadoc提供了用于处理此问题的示例代码,以供引用:

07-28 00:28