6

我正在使用Executors.newCachedThreadPool()andinvokeAll和 List of Callables 来进行长时间运行的多线程处理。我的主线程被阻塞,直到所有线程都完成并且我可以处理invokeAll. 但是,如果其中一个s 抛出异常并终止其他线程,我想invokeAll立即返回。Callable

使用execute而不是invokeAll会阻止第一个future.get()不需要是抛出执行的那个。

使用忙等待循环遍历所有期货并检查isDone()似乎也不是最好的方法。

4

1 回答 1

7

您可以使用更复杂的同步机制,例如锁存器、屏障或信号量,但请查看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();

代码非常简单。首先你executorServicecompletionService. 以后你用它一个接一个地提交任务。最后一行很关键。它需要完成的第一个任务并尝试检索结果。如果它抛出一个异常,它将在这里被重新抛出,并用ExecutionException

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

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

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

于 2013-01-10T18:48:55.773 回答