Возврат вне ордера из Java Futures
Единственная модель, которую я могу придумать для запуска нескольких подобных процессов (SIMD), используя
Java Futures (java.util.concurrent.Future<T>
) выглядит следующим образом:
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()
), если они еще не готовы?
Ответы
Ответ 1
Вы можете попробовать ExecutorCompletionService
:
http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html
Вы просто отправляете свои задачи и выполняете вызов до тех пор, пока не получите все фьючерсы.
Ответ 2
С помощью ListenableFuture
от Guava. Они позволяют вам в основном добавлять продолжение для выполнения, когда будущее завершено.
Ответ 3
Почему бы вам не добавить то, что вы хотите сделать на эту работу?
class Job extends Runnable {
public void run() {
// ...
T result = ....
// do something with the result.
}
}
Таким образом, он будет обрабатывать результат, как только он будет доступен, одновременно.;)
Ответ 4
A CompletionService
может быть опробован для доступных результатов.
Если все, что вам нужно, это результаты по мере их появления, мы написали AsyncCompleter
, который абстрагирует детали использования службы завершения, Он позволяет вам отправить Iterable<Callable<T>>
заданий и возвращает Iterable<T>
результатов, которые блокируются на next()
и возвращают результаты в порядке завершения.