Дождитесь завершения любого из Future <T>

У меня работает несколько асинхронных задач, и мне нужно дождаться завершения хотя бы одной из них (в будущем, вероятно, мне нужно будет дождаться завершения утилиты M из N). В настоящее время они представлены как Future, поэтому мне нужно что-то вроде

/**
 * Blocks current thread until one of specified futures is done and returns it. 
 */
public static <T> Future<T> waitForAny(Collection<Future<T>> futures) 
        throws AllFuturesFailedException

Есть что-нибудь подобное? Или что-то подобное, не обязательно для будущего. В настоящее время я перебираю коллекцию фьючерсов, проверяю, завершено ли это, затем сплю некоторое время и проверяю снова. Это выглядит не лучшим решением, потому что, если я сплю в течение длительного периода времени, добавляется нежелательная задержка, если я сплю в течение короткого периода времени, это может повлиять на производительность.

Я мог бы попробовать использовать

new CountDownLatch(1)

и уменьшить обратный отсчет, когда задача завершена и сделать

countdown.await()

, но я нашел это возможным, только если я буду контролировать будущее творение. Это возможно, но требует редизайна системы, потому что в настоящее время логика создания задач (отправка Callable в ExecutorService) отделена от решения ждать, какое будущее. Я мог бы также переопределить

<T> RunnableFuture<T> AbstractExecutorService.newTaskFor(Callable<T> callable)

и создайте пользовательскую реализацию RunnableFuture с возможностью прикрепить прослушиватель, чтобы получать уведомления о завершении задачи, затем присоединить такого прослушивателя к необходимым задачам и использовать CountDownLatch, но это означает, что я должен переопределить newTaskFor для каждого используемого ExecutorService - и, возможно, будет реализация которые не расширяют AbstractExecutorService. Я мог бы также попытаться обернуть данный ExecutorService для той же цели, но затем я должен украсить все методы, производящие Futures.

Все эти решения могут работать, но кажутся очень неестественными. Похоже, мне не хватает чего-то простого, например

WaitHandle.WaitAny(WaitHandle[] waitHandles)

в с #. Есть ли известные решения для такого рода проблем?

ОБНОВИТЬ:

Изначально у меня не было доступа к созданию будущего, поэтому не было элегантного решения. После редизайна системы я получил доступ к созданию Future и смог добавить countDownLatch.countdown () в процесс выполнения, затем я могу считать countDownLatch.await (), и все работает отлично. Спасибо за другие ответы, я не знал о ExecutorCompletionService, и он действительно может быть полезен в подобных задачах, но в данном конкретном случае его нельзя использовать, потому что некоторые Futures создаются без какого-либо исполнителя - фактическая задача отправляется на другой сервер через сеть, завершается удаленно и уведомление о завершении получено.

Ответы на вопрос(7)

Ваш ответ на вопрос