3 回答
TA贡献1815条经验 获得超10个赞
如果您使用的是Java 8,则可以使用CompletableFuture和CompletableFuture.allOf轻松完成此操作,它们仅在完成所有提供的CompletableFutures之后才应用回调。
// Waits for *all* futures to complete and returns a list of results.
// If *any* future completes exceptionally then the resulting future will also complete exceptionally.
public static <T> CompletableFuture<List<T>> all(List<CompletableFuture<T>> futures) {
CompletableFuture[] cfs = futures.toArray(new CompletableFuture[futures.size()]);
return CompletableFuture.allOf(cfs)
.thenApply(ignored -> futures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList())
);
}
TA贡献1804条经验 获得超7个赞
您可以使用ExecutorCompletionService。该文档甚至提供了一个具体用例的示例:
相反,假设您想使用任务集的第一个非空结果,忽略遇到异常的任何结果,并在第一个任务就绪时取消所有其他任务:
void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {
CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);
int n = solvers.size();
List<Future<Result>> futures = new ArrayList<Future<Result>>(n);
Result result = null;
try {
for (Callable<Result> s : solvers)
futures.add(ecs.submit(s));
for (int i = 0; i < n; ++i) {
try {
Result r = ecs.take().get();
if (r != null) {
result = r;
break;
}
} catch (ExecutionException ignore) {
}
}
} finally {
for (Future<Result> f : futures)
f.cancel(true);
}
if (result != null)
use(result);
}
这里要注意的重要一点是ecs.take()将获得第一个完成的任务,而不仅仅是第一个提交的任务。因此,您应该按照完成执行(或引发异常)的顺序获取它们。
添加回答
举报