Самый простой подход - использовать ExecutorService.invokeAll()
, который делает то, что вы хотите, в одной строке. На вашем языке вам нужно изменить или обернуть ComputeDTask
, чтобы реализовать Callable<>
, что может дать вам немного больше гибкости. Возможно, в вашем приложении есть значимая реализация Callable.call()
, но вот способ обернуть его, если не использовать Executors.callable()
.
ExecutorService es = Executors.newFixedThreadPool(2);
List<Callable<Object>> todo = new ArrayList<Callable<Object>>(singleTable.size());
for (DataTable singleTable: uniquePhrases) {
todo.add(Executors.callable(new ComputeDTask(singleTable)));
}
List<Future<Object>> answers = es.invokeAll(todo);
Как уже отмечали другие, вы можете использовать версию invokeAll()
для тайм-аута, если это необходимо. В этом примере answers
будет содержать набор Future
s, которые будут возвращать нули (см. Определение Executors.callable()
. Вероятно, вы хотите сделать небольшой рефакторинг, чтобы вы могли получить полезный ответ, или ссылка на базовый ComputeDTask
, но я не могу сказать из вашего примера.
Если неясно, обратите внимание, что invokeAll()
не вернется, пока не будут выполнены все задачи. (т. е. все Future
в вашей коллекции answers
сообщат .isDone()
, если их спросят.) Это позволяет избежать всего ручного выключения, awaitTermination и т. д. и позволяет вам аккуратно использовать этот ExecutorService
для нескольких циклов при желании.
Есть несколько связанных вопросов по SO:
Ни один из этих вопросов не является строго актуальным для вашего вопроса, но они дают немного информации о том, как люди думают, что Executor
/ ExecutorService
следует использовать.