Espere até que qualquer um dos Future <T> seja concluído

Eu tenho poucas tarefas assíncronas em execução e preciso aguardar até que pelo menos uma delas tenha terminado (no futuro, provavelmente, precisarei aguardar que o utilitário M das N tarefas esteja concluído). Atualmente eles são apresentados como Futuro, então eu preciso de algo como

/**
 * 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

Existe algo assim? Ou qualquer coisa semelhante, não é necessária para o futuro. Atualmente faço um loop através da coleta de futuros, verifico se um está acabado, depois durmo por algum tempo e checo novamente. Isso parece não ser a melhor solução, porque se eu durmo por um longo período, o atraso indesejado é adicionado, se eu durmo por curto período, então isso pode afetar o desempenho.

Eu poderia tentar usar

new CountDownLatch(1)

e diminuir a contagem regressiva quando a tarefa estiver concluída e

countdown.await()

, mas só achei possível se eu controlar a criação do Futuro. É possível, mas requer o redesign do sistema, porque atualmente a lógica de criação de tarefas (envio de Callable para ExecutorService) é separada da decisão de esperar por qual Future. Eu também poderia substituir

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

e criar implementação personalizada do RunnableFuture com capacidade de anexar listener para ser notificado quando a tarefa for concluída, anexar esse ouvinte às tarefas necessárias e usar o CountDownLatch, mas isso significa que eu tenho que substituir newTaskFor para cada ExecutorService que eu uso - e potencialmente haverá implementação que não estendem o AbstractExecutorService. Eu também poderia tentar embrulhar o ExecutorService para o mesmo propósito, mas então eu tenho que decorar todos os métodos de produção do Futures.

Todas essas soluções podem funcionar, mas parecem pouco naturais. Parece que estou sentindo falta de algo simples, como

WaitHandle.WaitAny(WaitHandle[] waitHandles)

em c #. Existem soluções bem conhecidas para esse tipo de problema?

ATUALIZAR:

Originalmente, eu não tinha acesso à criação do Future, então não havia uma solução elegante. Depois de redesenhar o sistema, consegui acesso à criação do Future e consegui adicionar countDownLatch.countdown () ao processo de execução, então eu posso countDownLatch.await () e tudo funciona bem. Obrigado por outras respostas, eu não sabia sobre ExecutorCompletionService e de fato pode ser útil em tarefas semelhantes, mas neste caso particular, não poderia ser usado porque alguns futuros são criados sem qualquer executor - tarefa real é enviada para outro servidor via rede, conclui remotamente e a notificação de conclusão é recebida.

questionAnswers(7)

yourAnswerToTheQuestion