ExecutorService, como aguardar a conclusão de todas as tarefas

Qual é a maneira mais simples de esperar por todas as tarefas deExecutorService terminar? Minha tarefa é principalmente computacional, então eu só quero executar um grande número de tarefas - uma em cada núcleo. No momento, minha configuração fica assim:

ExecutorService es = Executors.newFixedThreadPool(2);
for (DataTable singleTable : uniquePhrases) {   
    es.execute(new ComputeDTask(singleTable));
}
try{
    es.wait();
} 
catch (InterruptedException e){
    e.printStackTrace();
}

ComputeDTask implementa executável. Isso parece executar as tarefas corretamente, mas o código travawait() comIllegalMonitorStateException. Isso é estranho, porque eu brinquei com alguns exemplos de brinquedos e pareceu funcionar.

uniquePhrases contém várias dezenas de milhares de elementos. Devo estar usando outro método? Estou procurando algo o mais simples possível

questionAnswers(14)

yourAnswerToTheQuestion