java - 为什么 ThreadPoolExecutor 的 afterExecute() 异常为 null?

标签 java multithreading threadpool threadpoolexecutor futuretask

我想在 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.

这意味着可抛出的实例将是RuntimeExceptionError检查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/

相关文章:

java - 转换实现 Runnable 的对象

java - ExecutorService 池中的数组中所有元素的总和不起作用

java - 在Java中指定任务顺序执行

java - 从服务器接收数据时出现 NoSuchElementFoundException

java - 验证文本字符串是否与 java 中预先确定的格式相匹配

asp.net - MVC Ajax请求不阻塞主线程

python - 我怎样才能让这两个线程一个接一个地不断运行python?

java - RequestDispatcher.forward() 和 HttpServletResponse.sendRedirect() 有什么区别?

java - 基于类选择元素的 XPath

java - 多个线程如何在同一对象上拥有 "locked"(如线程转储所示)