假设我有以下代码:

ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(myRunnable);

现在,如果 myRunnable 抛出一个 RuntimeExcpetion, ,我怎样才能抓住它?一种方法是提供我自己的 ThreadFactory 实施到 newSingleThreadExecutor() 并设置自定义 uncaughtExceptionHandlers 为 Thread是从中出来的。另一种方法是包裹 myRunnable 给本地人(匿名) Runnable 包含一个 try-catch 块。也许还有其他类似的解决方法。但...不知怎的,这感觉很脏,我觉得它不应该这么复杂。有干净的解决方案吗?

有帮助吗?

解决方案

在清洁解决方法是使用ExecutorService.submit()代替execute()的。这将返回一个Future,你可以用它来检索结果或任务的异常:

ExecutorService executor = Executors.newSingleThreadExecutor();
Runnable task = new Runnable() {
  public void run() {
    throw new RuntimeException("foo");
  }
};

Future<?> future = executor.submit(task);
try {
  future.get();
} catch (ExecutionException e) {
  Exception rootException = e.getCause();
}

其他提示

装饰在另一个可运行其捕捉运行时异常和处理它们可运行:

public class REHandler implements Runnable {
    Runnable delegate;
    public REHandler (Runnable delegate) {
        this.delegate = delegate;
    }
    public void run () {
        try {
            delegate.run ();
        } catch (RuntimeException e) {
            ... your fancy error handling here ...
        }
    }
}

executor.execute(new REHandler (myRunnable));

为什么不打电话 ExecutorService#submit(), ,得到 Future 返回,然后在调用时自己处理可能的异常 Future#get() ?

skaffman是正确的,使用submit是最干净的方法。另一种方法是继承 ThreadPoolExecutor 并覆盖afterExecute(Runnable, Throwable)。如果按照这个方法的一定要打电话execute(Runnable) 而非submit(Runnable)afterExecute将不会被调用。

每API的描述:

  

方法完成时调用   在给定的Runnable的执行。这个   方法由该线程调用该   执行任务。如果非空,在   Throwable的是未被捕获   的 RuntimeException Error 引起   执行突然终止。

     

注意:当操作被封闭在   任务(如FutureTask)任一   明确地或通过方法如   提交,这些任务对象捕捉和   维护计算异常,   所以它们不会导致突然   终止,并且内部   例外的不传递给此   方法

任务(CallableRunnable)提交 ThreadPoolExecutors 将被转换成 FuturnTask, 包含一个道具命名的 callable 就等于你的任务提交。FuturnTask有其自己的 run 方法如下。所有异常或抛出扔在 c.call() 将被逮住,并投入的支柱名为 outcome.打电话时FuturnTask的 get 方法, outcome 会倒掉

FuturnTask.从Jdk1.8源代码

public void run() {
        ...
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    // save ex into `outcome` prop
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        }
        ...
    }

如果你想赶上的例外:

      1.skaffman的答案
      2.复盖`afterExecute`当你新的一ThreadPoolExecutor
        @Override
        protected void afterExecute(Runnable r, Throwable t) {
            super.afterExecute(r, t);
            Throwable cause = null;
            if (t == null && r instanceof Future) {
                try {
                    ((Future<?>) r).get();
                } catch (InterruptedException | ExecutionException e) {
                    cause = e;
                }
            } else if (t != null) {
                cause = t;
            }
            if (cause != null) {
                // log error
            }
        }
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top