等待未来的名单 [英] Waiting on a list of Future

查看:19
本文介绍了等待未来的名单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a method which returns a List of futures

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

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

Now I want to wait until either all futures are done processing successfully or any of the tasks whose output is returned by a future throws an exception. Even if one task throws an exception, there is no point in waiting for the other 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 个期货抛出异常,那么我将不必要地等待前 3 个期货可用.

But the problem here is if, for example, the 4th future throws an exception, then I will wait unnecessarily for the first 3 futures to be available.

如何解决这个问题?会以任何方式倒计时闩锁帮助吗?我无法使用 Future isDone 因为 java 文档说

How to solve this? Will count down latch help in any way? I'm unable to use Future isDone because the java doc says

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.

推荐答案

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

You can use a CompletionService to receive the futures as soon as they are ready and if one of them throws an exception cancel the processing. Something like this:

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;
      }
}

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

I think you can further improve to cancel any still executing tasks if one of them throws an error.

这篇关于等待未来的名单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆