您可以使用更复杂的同步机制,例如锁存器、屏障或信号量,但请查看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()
十次来等待所有任务完成。只要至少有一个任务完成,每个调用都会阻塞。