12

我能想到的使用 Java Futures ( java.util.concurrent.Future<T>) 运行多个类似进程 (SIMD) 的唯一模型如下:

class Job extends Callable<T> {
  public T call() {
    // ...
  }
}
List<Job> jobs = // ...
List<Future<T>> futures = ExecutorService.invokeAll(jobs);
for (Future<T> future : futures) {
  T t = future.get();
  // Do something with t ...
}

该模型的问题在于,如果作业 0 需要很长时间才能完成,但作业 1、2 和 3 已经完成,则for循环将等待从作业 0 获取返回值。

是否有任何模型可以让我在每个Future结果可用时获得每个结果,而无需调用Future.isDone()和忙于等待(或调用Thread.sleep())(如果还没有准备好)?

4

4 回答 4

15

你可以试试ExecutorCompletionService

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html

您只需提交您的任务并调用 take 直到您收到所有 Futures。

于 2011-05-04T11:01:15.880 回答
14

考虑使用ListenableFuture来自Guava。它们让您基本上可以在未来完成时添加一个继续执行。

于 2011-05-04T11:01:00.687 回答
0

你为什么不把你想做的事情添加到工作中呢?

class Job extends Runnable {
  public void run() {
    // ...
    T result = ....
    // do something with the result.
  }
}

这样,它会在结果可用时同时处理结果。;)

于 2011-05-04T11:19:40.803 回答
0

CompletionService可以轮询A以获得可用结果。

但是,如果您想要的只是可用的结果,那么我们编写了一个AsyncCompleter抽象出完成服务使用细节的方法。它允许您提交一个Iterable<Callable<T>>作业并返回一个Iterable<T>阻塞next()的结果并按完成顺序返回结果。

于 2011-05-04T23:13:01.507 回答