awaitTermination
обычно немного безопаснее, в то время как shutdownNow
более принудительно. Обычно хорошей идеей является использование awaitTermination
в функциональном методе или даже в рабочем режиме, если вы хотите, чтобы исполнитель закрылся как можно скорее, но только после того, как он выполнил все, что было создано. Другими словами, когда нет активных задач, которые выполняет исполнитель.
Ex.)
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime.availableProcessors);
Observable.of(items).schedule(Schedulers.from(executor)).flatMap(item -> {
... // this block represents a task that the executor will execute in a worker thread
}).onSubscribe(onNext ->
logItem(onNext), throwable ->
throwable.printStackTrace(), /* onComplete */ () ->
executor.awaitTermination(60, TimeUnit.Seconds)
);
... // you need to shutdown asap because these other methods below are also doing some computation/io-intensive stuff
Теперь, когда этот метод завершится, он вызовет awaitTermination
, который либо немедленно закроет пул, если он не выполняет никаких задач, либо подождет до 60 секунд, если задачи все еще выполняются.
Потоки или работники перестают быть активными в течение 60 секунд бездействия в большинстве случаев, так как обычно это значение по умолчанию.
С другой стороны, если вы хотите, чтобы задачи перестали выполняться, как только (для некоторых примеров) было сгенерировано исключение, произошло нарушение безопасности или произошел сбой другого модуля / службы, вы можете использовать shutdownNow () немедленно остановить все задачи без возможности ожидания.
Мой совет по выбору между этими двумя вариантами: использовать shutdownNow
в блоке перехвата, если вы не хотите, чтобы задачи продолжали выполняться, если есть исключение, т. Е. Больше нет причин возвращать список элементов для клиента, учитывая, что один из элементов не был добавлен в список.
В противном случае, я бы рекомендовал использовать awaitTermination
после вашего try-catch, установленного на одну минуту, для безопасного закрытия пула потоков, как только он выполнил все задачи, которые вы ему дали. Но делайте это только в том случае, если вы знаете, что исполнитель не будет нести ответственность за выполнение каких-либо дополнительных задач в будущем.
Простой shutdown
, если это вариант для вас, также является хорошим методом. shutdown
будет отклонять все входящие задачи, но ждать, пока текущие задачи не будут завершены, согласно документации Oracle.
Если вы не уверены, когда вам нужно закрыть исполнителя, было бы неплохо использовать метод @PreDestroy
, чтобы исполнитель выполнял незадолго до вызова метода destroy для вашего компонента:
@PreDestroy
private void cleanup(){
executor.shutdown();
}