Um pouco tarde para o jogo, mas por uma questão de conclusão ...
Em vez de "esperar" que todas as tarefas terminem, você pode pensar em termos do princípio de Hollywood: "não me ligue, eu te ligo" - quando terminar. Eu acho que o código resultante é mais elegante ...
Goiaba oferece algumas ferramentas interessantes para fazer isso.
Um exemplo ::
Agrupar um ExecutorService em um ListeningExecutorService ::
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
Envie uma coleção de callables para execução:
for (Callable<Integer> callable : callables) {
ListenableFuture<Integer> lf = service.submit(callable);
// listenableFutures is a collection
listenableFutures.add(lf)
});
Agora a parte essencial:
ListenableFuture<List<Integer>> lf = Futures.successfulAsList(listenableFutures);
Anexe um retorno de chamada ao ListenableFuture, que você poderá usar para ser notificado quando todos os futuros forem concluídos:
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);
}
});
Isso também oferece a vantagem de que você pode coletar todos os resultados em um único local após o término do processamento ...
Mais informações aqui