一个子线程抛出异常后立即返回主线程

时间:2013-01-10 18:43:37

标签: java multithreading exception executorservice

我正在使用Executors.newCachedThreadPool()invokeAll列表Callable来执行长时间运行的多线程处理。 我的主线程被阻塞,直到所有线程完成,我可以处理invokeAll返回的Futures。但是,如果其中一个invokeAll抛出异常并终止其他线程,我希望Callable立即返回。

使用execute代替invokeAll会阻止第一个future.get(),而isDone()不一定是引发执行的那个。{/ p>

使用忙碌等待循环查看所有期货并检查{{1}}似乎也不是最佳方式。

1 个答案:

答案 0 :(得分:6)

您可以使用更复杂的同步机制,如锁存器,障碍或信号量,但请查看ExecutorCompletionService。它是围绕ExecutorService的轻量级包装器,允许您监听第一个完成的任务。这是一个简单的例子:

final ExecutorService executorService = Executors.newCachedThreadPool();
final ExecutorCompletionService<String> completionService = 
            new ExecutorCompletionService<String>(executorService);
for (int i = 0; i < 10; ++i) {
    completionService.submit(new Task());
}
completionService.take().get();

代码非常简单。首先用executorService包裹completionService。之后你用它来一个接一个地提交任务。最后一行至关重要。它完成第一个任务并尝试检索结果。如果它抛出异常,它将在此重新抛出,包含ExecutionException

try {
    completionService.take().get();
} catch (ExecutionException e) {
    e.getCause();       //this was thrown from task!
}

catch块内,您可以以某种方式处理异常,例如取消剩余的任务或关闭整个线程池。

当然,您可以通过拨打take()十次来等待所有任务完成。只要至少完成一项任务,每次调用都会阻止。