等待未来的名单

新手上路,请多包涵

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

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

现在我想等到所有 futures 都成功完成处理,或者 futures 返回输出的任何任务抛出异常。即使一个任务抛出异常,等待其他 futures 也是没有意义的。

简单的方法是

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 个 future 抛出异常,那么我将不必要地等待前 3 个 futures 可用。

如何解决这个问题?倒计时闩锁会以任何方式提供帮助吗?我无法使用 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.

原文由 user93796 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 361
2 个回答

您可以使用 CompletionService 在期货准备就绪后立即接收期货,如果其中之一抛出异常,则取消处理。是这样的:

 Executor executor = Executors.newFixedThreadPool(4);
CompletionService<SomeResult> completionService =
       new ExecutorCompletionService<SomeResult>(executor);

//4 tasks
for(int i = 0; i < 4; i++) {
   completionService.submit(new Callable<SomeResult>() {
       public SomeResult call() {
           ...
           return result;
       }
   });
}

int received = 0;
boolean errors = false;

while(received < 4 && !errors) {
      Future<SomeResult> resultFuture = completionService.take(); //blocks if none available
      try {
         SomeResult result = resultFuture.get();
         received ++;
         ... // do something with the result
      }
      catch(Exception e) {
             //log
         errors = true;
      }
}

我认为您可以进一步改进以取消任何仍在执行的任务,如果其中一个任务抛出错误。

原文由 dcernahoschi 发布,翻译遵循 CC BY-SA 4.0 许可协议

如果您使用的是 Java 8 ,那么您可以使用 CompletableFuture 和 CompletableFuture.allOf 更轻松地完成此操作,它仅在所有提供的 CompletableFuture 完成后应用回调。

 // 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())
            );
}

原文由 Andrejs 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题