Самое близкое, что я могу придумать, это использовать CompletionService
для накопления результатов по мере их завершения.
Простой пример:
ExecutorService executor = Executors.newSingleThreadExecutor(); // Create vanilla executor service.
CompletionService<Result> completionService = new ExecutorCompletionService<Result>(executor); // Completion service wraps executor and is notified of results as they complete.
Callable<Result> callable = new MyCallable();
executor.submit(callable); // Do not store handle to Future here but rather obtain from CompletionService when we *know* the result is complete.
Future<Result> fut = completionService.take(); // Will block until a completed result is available.
Result result = fut.get(); // Will not block as we know this future represents a completed result.
Я бы не рекомендовал оборачивать это за интерфейс Iterator
, так как метод Future
get()
может выдать два возможных проверенных исключения: ExecutionException
и InterruptedException
, и поэтому вам нужно будет перехватить и проглотить или отбросить их как RuntimeException
с, но это не очень хорошая вещь. Кроме того, ваши Iterator
hasNext()
или next()
методы потенциально должны были бы блокироваться, если выполнялась задача, что можно было бы считать нелогичным для клиентов, использующих Iterator
. Вместо этого я бы реализовал свой собственный более описательный интерфейс; например,
public interface BlockingResultSet {
/**
* Returns next result when it is ready, blocking is required.
* Returns null if no more results are available.
*/
Result take() throws InterruptedException, ExecutionException;
}
(Методы, называемые take()
, обычно представляют блокирующий вызов в пакете java.util.concurrent
).