等待未来的清单

我有一种返回List期货的方法


List<Future<O>> futures = getFutures();

现在,我要等待,直到所有期货都成功完成处理,或者所有由期货返回输出的任务都引发异常。即使一项任务引发异常,也没有必要等待其他期货。


简单的方法是


wait() {


   For(Future f : futures) {

     try {

       f.get();

     } catch(Exception e) {

       //TODO catch specific exception

       // this future threw exception , means somone could not do its task

       return;

     }

   }

}

但是这里的问题是,例如,如果第4个期货抛出异常,那么我将不必要地等待前3个期货可用。


如何解决呢?会以任何方式倒计时闩锁帮助吗?我无法使用Future,isDone因为Java文档说


boolean isDone()

Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation -- in all of these cases, this method will return true.


偶然的你
浏览 323回答 3
3回答

动漫人物

如果您使用的是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) {&nbsp; &nbsp; CompletableFuture[] cfs = futures.toArray(new CompletableFuture[futures.size()]);&nbsp; &nbsp; return CompletableFuture.allOf(cfs)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .thenApply(ignored -> futures.stream()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .map(CompletableFuture::join)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .collect(Collectors.toList())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; );}

三国纷争

您可以使用ExecutorCompletionService。该文档甚至提供了一个具体用例的示例:相反,假设您想使用任务集的第一个非空结果,忽略遇到异常的任何结果,并在第一个任务就绪时取消所有其他任务:void solve(Executor e, Collection<Callable<Result>> solvers) throws InterruptedException {&nbsp; &nbsp; CompletionService<Result> ecs = new ExecutorCompletionService<Result>(e);&nbsp; &nbsp; int n = solvers.size();&nbsp; &nbsp; List<Future<Result>> futures = new ArrayList<Future<Result>>(n);&nbsp; &nbsp; Result result = null;&nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; for (Callable<Result> s : solvers)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; futures.add(ecs.submit(s));&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < n; ++i) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Result r = ecs.take().get();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (r != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; result = r;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (ExecutionException ignore) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; } finally {&nbsp; &nbsp; &nbsp; &nbsp; for (Future<Result> f : futures)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; f.cancel(true);&nbsp; &nbsp; }&nbsp; &nbsp; if (result != null)&nbsp; &nbsp; &nbsp; &nbsp; use(result);}这里要注意的重要一点是ecs.take()将获得第一个完成的任务,而不仅仅是第一个提交的任务。因此,您应该按照完成执行(或引发异常)的顺序获取它们。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java