Un poco tarde para el juego, pero para completarlo ...
En lugar de 'esperar' a que finalicen todas las tareas, puede pensar en términos del principio de Hollywood: "no me llame, lo llamaré", cuando haya terminado. Creo que el código resultante es más elegante ...
La guayaba ofrece algunas herramientas interesantes para lograr esto.
Un ejemplo ::
Envuelva un ExecutorService en ListeningExecutorService ::
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
Enviar una colección de invocables para su ejecución ::
for (Callable<Integer> callable : callables) {
ListenableFuture<Integer> lf = service.submit(callable);
// listenableFutures is a collection
listenableFutures.add(lf)
});
Ahora la parte esencial:
ListenableFuture<List<Integer>> lf = Futures.successfulAsList(listenableFutures);
Adjunte una devolución de llamada al ListenableFuture, que puede usar para recibir notificaciones cuando se completen todos los futuros ::
Futures.addCallback(lf, new FutureCallback<List<Integer>>() {
@Override
public void onSuccess(List<Integer> result) {
log.info("@@ finished processing {} elements", Iterables.size(result));
// do something with all the results
}
@Override
public void onFailure(Throwable t) {
log.info("@@ failed because of :: {}", t);
}
});
Esto también ofrece la ventaja de que puede recopilar todos los resultados en un solo lugar una vez que finalice el procesamiento ...
Más información aquí.