Каков наилучший способ узнать, когда все представленные задачи были выполнены службой Executor - PullRequest
0 голосов
/ 02 сентября 2018

здесь два варианта, просто запутайте, какой из них лучше выбрать.

Вариант 1:

ExecutorService es = Executors.newFixedThreadPool(4);
List<Runnable> tasks = getTasks();
CompletableFuture<?>[] futures = tasks.stream()
                               .map(task -> CompletableFuture.runAsync(task, es))
                               .toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futures).join();    
es.shutdown();

Вариант 2:

ExecutorService es = Executors.newFixedThreadPool(4);
List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
    futures.add(es.submit(task));
}

for(Future<?> future : futures) {
    try {
        future.get();
    }catch(Exception e){
        // do logging and nothing else
    }
}
es.shutdown();

Здесь выкладываю future.get (); в try catch это хорошая идея, верно?

Ответы [ 3 ]

0 голосов
/ 02 сентября 2018

Существует еще один способ дождаться завершения всех задач. После того, как вы отправили все свои задания, позвоните

es.shutdown()
es.awaitTermination(Long.MAX_VALUE, TimeUnit.NANO_SECONDS)

Документы Oracle по Java читать:

shutdown [...] Инициирует упорядоченное завершение работы, при котором выполняются ранее отправленные задачи.

awaitTermination [...] Блокирует до тех пор, пока все задачи не завершат выполнение после запроса на выключение, или не истечет время ожидания, или текущий поток не прервется, в зависимости от того, что произойдет раньше.

Относительно тайм-аута: при указанных выше значениях пул потоков завершится только через 300 лет.

0 голосов
/ 02 сентября 2018

Аналогично предложению Aris_Kortex,

List<CompletableFuture<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
    futures.add(CompletableFuture.runAsync(task, es));
}

, а затем создайте объединенное CompletableFuture:

CompletableFuture<Void> cf = CompletableFuture.allOf(futures.toArray(futires.size()));

тогда вы можете синхронно ждать всех заданий:

cf.get();

синхронно с таймаутом:

cf.get(1, TimeUnit.SECOND);

асинхронно:

cf.thenRun(()->{finalActions();});
0 голосов
/ 02 сентября 2018

Поскольку вы фактически удерживаете каждый отправленный Future в списке фьючерсов, выполняя это:

List< Future<?>> futures = new ArrayList<>();
for(Runnable task : taskList) {
    futures.add(es.submit(task));
}

Вы можете очень легко проверить, все ли выполненные задания выполняются, просто вызвав метод Future#isDone, который вернет true или false в зависимости от того, завершена ли задача или нет. Подробнее об этом вы можете узнать в соответствующей документации здесь .

Следовательно, учитывая вышесказанное, вы вполне можете создать простой вспомогательный метод, который будет перебирать список ваших фьючерсов и проверять их состояние. Например:

private boolean areJobsDone() {
    return futures.stream()
        .allMatch(Future::isDone);
}

Обратите внимание, что в отличие от метода Future#get, isDone не является блокирующим (так как не ожидает, пока задача вернет свой результат), поскольку он эффективно запрашивает свое состояние.

С этим вы можете пойти дальше и проверить состояние ваших исполняемых файлов, заблокировав поток с помощью цикла, который вызовет вспомогательный метод, прежде чем продолжить.

Надеюсь, это поможет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...