如何在FutureTask中捕获异常

Thi*_*ler 21 java concurrency executorservice futuretask

在发现在Java 1.6上FutureTask运行Executors.newCachedThreadPool()(以及从Eclipse中)吞下Runnable.run()方法中的异常后,我试图找到一种方法来捕获这些,而不向我的所有Runnable实现添加throw/catch .

API建议覆盖FutureTask.setException()应该有助于此:

导致此未来报告ExecutionException,并将给定的throwable作为其原因,除非已设置或已取消此Future.在计算失败时,run方法在内部调用此方法.

但是,似乎没有调用此方法(使用调试器运行显示异常被捕获FutureTasksetException未被调用).我写了以下程序来重现我的问题:

public class RunTest {
    public static void main(String[] args) {
        MyFutureTask t = new MyFutureTask(new Runnable() {

            @Override
            public void run() {
                throw new RuntimeException("Unchecked exception");

            }
        });

        ExecutorService service = Executors.newCachedThreadPool();
        service.submit(t);
    }
}

public class MyFutureTask extends FutureTask<Object> {

    public MyFutureTask(Runnable r) {
        super(r, null);
    }

    @Override
    protected void setException(Throwable t) {
        super.setException(t);
        System.out.println("Exception: " + t);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的主要问题是:如何捕获FutureTask中引发的异常?为什么不setException打电话?

另外我想知道为什么Thread.UncaughtExceptionHandler机制没有使用FutureTask,有什么理由吗?

gus*_*afc 20

setException可能不是用于覆盖,但是如果需要,可以将结果设置为异常.你想要做的是覆盖done()方法并尝试获得结果:

public class MyFutureTask extends FutureTask<Object> {

    public MyFutureTask(Runnable r) {
        super(r, null);
    }

    @Override
    protected void done() {
        try {
            if (!isCancelled()) get();
        } catch (ExecutionException e) {
            // Exception occurred, deal with it
            System.out.println("Exception: " + e.getCause());
        } catch (InterruptedException e) {
            // Shouldn't happen, we're invoked when computation is finished
            throw new AssertionError(e);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sou*_*ink 12

你试过用过UncaughtExceptionHandler吗?

  • 您需要实现该UncaughtExceptionHandler接口.
  • 要设置UncaughtExceptionHandlerfor pool线程,请ThreadFactoryExecutor.newCachedThreadPool(ThreadFactory)调用中提供.
  • 您可以为创建的线程设置UncaughtExceptionHandler setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)

提交任务ExecutorService.execute,因为只有从提交的任务中抛出的异常execute才能使其成为未捕获的异常处理程序.对于随ExecutorService.submit任何抛出异常提交的任务,将被视为任务返回值的一部分.如果使用submit提交的任务以异常终止,则在调用时重新执行Future.get,包装在ExecutionException


小智 9

一个更好的解决方案: Java FutureTask完成检​​查

当您调用futureTask.get()以检索计算结果时,如果底层Runnable/ Callable抛出异常,它将抛出异常(ExecutionException).

ExecutionException.getCause()将返回Runnable/ Callable抛出的异常.

如果Runnable/ Callable被取消,它也会抛出不同的异常.