Espera hasta que se termine algo de Futuro <T>

Tengo pocas tareas asíncronas en ejecución y necesito esperar hasta que al menos una de ellas haya finalizado (en el futuro probablemente tendré que esperar a que se terminen las tareas M de N). Actualmente se presentan como Future, así que necesito 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

¿Hay algo como esto? O algo similar, no necesario para el futuro. Actualmente recorro la recopilación de futuros, verifico si uno está terminado, luego duermo por un tiempo y verifico nuevamente. Parece que no es la mejor solución, porque si duermo durante un período prolongado, se agrega un retraso no deseado, si duermo durante un período corto, puede afectar el rendimiento.

Podría intentar usar

new CountDownLatch(1)

y disminuir la cuenta atrás cuando la tarea está completa y hacer

countdown.await()

, pero lo encontré posible solo si controlo la creación Futura. Es posible, pero requiere un nuevo diseño del sistema, ya que actualmente la lógica de la creación de tareas (el envío de Callable a ExecutorService) está separada de la decisión de esperar para qué Futuro. También podría anular

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

y cree una implementación personalizada de RunnableFuture con la capacidad de adjuntar la escucha para que se le notifique cuando finalice la tarea, luego adjunte dicha escucha a las tareas necesarias y use CountDownLatch, pero eso significa que debo anular newTaskFor para cada ExecutorService que use, y potencialmente habrá implementación Que no extienden AbstractExecutorService. También podría intentar envolver el ExecutorService con el mismo propósito, pero luego tengo que decorar todos los métodos que produzcan Futuros.

Todas estas soluciones pueden funcionar pero parecen muy poco naturales. Parece que me estoy perdiendo algo simple, como

WaitHandle.WaitAny(WaitHandle[] waitHandles)

Cía#. ¿Hay soluciones bien conocidas para este tipo de problema?

ACTUALIZAR:

Originalmente no tenía acceso a la creación del Futuro en absoluto, por lo que no había una solución elegante. Después de rediseñar el sistema, obtuve acceso a la creación del Futuro y pude agregar countDownLatch.countdown () al proceso de ejecución, luego puedo contarDownLatch.await () y todo funciona bien. Gracias por otras respuestas, no conocía ExecutorCompletionService y, de hecho, puede ser útil en tareas similares, pero en este caso particular no se pudo usar porque algunos Futuros se crean sin ningún ejecutor. La tarea real se envía a otro servidor a través de la red. se completa de forma remota y se recibe la notificación de finalización.

Respuestas a la pregunta(7)

Su respuesta a la pregunta