Таким образом, рекомендуемая самой Oracle рекомендация по отключению ExecutorService
будет выглядеть следующим образом:
@PreDestroy
public void cleanUp(){
executorService.shutdown();
try {
if (executorService.awaitTermination(TIMEOUT, TimeUnit.MILLISECONDS)) {
executorService.shutdownNow();
}
} catch (InterruptedException e) {
executorService.shutdownNow();
}
}
Это также позаботится об отмене любых незавершенных задач. Мне интересно , когда приведенный выше фрагмент кода предпочтительнее следующего:
private List<Future> tasks = Collections.EMPTY_LIST;
public void doStuff(){
for (Service service : services) {
Future<?> future = executorService.submit(()->service.update(args));
tasks.add(task);
}
}
@PreDestroy
public void cleanUp() {
for (Future task : tasks) {
task.cancel(false);
}
}
Последнее позволит завершать запущенные задачи, не прерывая их (tasks.cancel(false)
). В этом подходе нет времени ожидания, поэтому бесконечный цикл в задаче предотвратит остановку приложения. Кроме того, у нас остается работающая служба исполнителей: но должны ли мы действительно заботиться об этом, если есть уверенность, что никакие другие задачи не могут быть отправлены после завершения отмененных задач?
Меня больше всего интересует то, что считается наилучшей практикой в ситуации, когда кто-то хочет дождаться завершения / завершения задач, прежде чем приступить к фактическому отключению. Почему мы на самом деле заботимся о закрытии самой службы исполнителя?
Имхо, иметь список фьючерсов, который можно было бы отменить при закрытии приложения, - гораздо более чистое решение, поскольку можно было бы выбрать, какие из них следует прервать, а какие ждать до завершения.
Любые более сложные идеи по этому поводу приветствуются.
Все они являются частью bean-компонента Spring, как вы могли бы понять из аннотации @PotsDestroy
, использованной для обозначения метода cleanUp
в качестве ловушки отключения для очистки задач службы executors.