Как ждать, пока все представленные задачи в ExecutorService будут завершены без выключения?
Представьте, что мы просматриваем коллекцию и отправляем задачи для выполнения в фоновом режиме.
class Processor {
public void process(Iterable<Item> items, ExecutorService executorService) {
for (Item item : items) {
doStandardProcess(item);
if (needSpecialProcess(item)) {
executorService.submit(createSpecialTaskFor(item));
}
}
}
}
Ход программы выглядит так:
- получать предметы откуда-то
- создать процессор и обработать их
- отправить результат куда-нибудь
Результат зависит от фоновой обработки, поэтому на стр.3 следует дождаться завершения всех задач. Я знаю, что это может быть достигнуто путем комбинации shutdown()
а также awaitTermination()
, но я не хочу выключать сервис. Также есть возможность позвонить invokeAll(List tasks)
, но, как вы видите, задачи создаются одна за другой во время обхода.
Как я могу добиться ожидания завершения с данными ограничениями?
PS Если было неясно, другое ограничение - запускать фоновые задачи параллельно с обходом элементов, потому что фоновые задачи занимают в 100 раз больше времени, чем базовая операция обработки.
2 ответа
Вы можете хранить фьючерсы:
List<Future> futures = new ArrayList<> ();
//in the for loop
futures.add(executorService.submit(createTaskFor(item)));
//after for loop + add exception handling
for (Future f : futures) f.get();
//at this point all tasks have finished
List<Callable<Foo>> toProcess = new ArrayList<>();
for (Item item : items) {
if (needProcess(item)) {
toProcess.add(createTaskFor(item));
}
}
executorService.invokeAll(toProcess);