Подтвердить что ты не робот

Разница между выключением и выключением.

Я хочу знать основное различие между shutdown() и shutdownNow() для закрытия Executor Service? Насколько я понял shutdown() следует использовать для изящного выключения, что означает все задачи, запускаемые и поставленные в очередь для обработки, но не запущенные, должны быть завершены, а shutdownNow() завершает резкое, что означает, что некоторые незавершенные задачи отменены, а также отмененные задачи также отменены. Есть ли что-либо еще, что неявное/явное, что мне не хватает?

P.S: Я нашел еще один вопрос в qaru.site/info/21305/..., но не совсем то, что я хочу знать.

4b9b3361

Ответ 1

Таким образом, вы можете думать об этом так:

  • shutdown() просто сообщит службе-исполнителю, что он не может принимать новые задачи, но уже отправленные задачи продолжают выполняться
  • shutdownNow() будет делать то же самое И будет попытаться отменить уже отправленные задачи, прервав соответствующие потоки. Обратите внимание, что если ваши задачи игнорируют прерывание, shutdownNow будет вести себя точно так же, как shutdown.

Вы можете попробовать пример ниже и заменить shutdown на shutdownNow, чтобы лучше понять разные пути выполнения:

  • с shutdown, вывод Still waiting after 100ms: calling System.exit(0)..., поскольку выполняемая задача не прервана и продолжает работать.
  • с shutdownNow, вывод interrupted и Exiting normally..., поскольку выполняемая задача прерывается, прерывает прерывание и останавливает то, что она делает (прерывает цикл while).
  • с shutdownNow, если вы закомментируете строки в цикле while, вы получите Still waiting after 100ms: calling System.exit(0)..., потому что прерывание больше не обрабатывается запущенной задачей.
public static void main(String[] args) throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(1);
    executor.submit(new Runnable() {

        @Override
        public void run() {
            while (true) {
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("interrupted");
                    break;
                }
            }
        }
    });

    executor.shutdown();
    if (!executor.awaitTermination(100, TimeUnit.MICROSECONDS)) {
        System.out.println("Still waiting after 100ms: calling System.exit(0)...");
        System.exit(0);
    }
    System.out.println("Exiting normally...");
}

Ответ 2

Из javadocs:

void shutdown

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

List<Runnable> shutdownNow()

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

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

Например, типичные реализации будут отменить через Thread.interrupt(), поэтому любая задача, которая не отвечает на прерывания никогда не прекратится.

Возвращает: список задач, которые никогда не запускались

Ответ 3

  • shutdown():

Чтобы завершить потоки внутри ExecutorService, вы вызываете его метод shutdown(). ExecutorService не будет закрыт немедленно, но он больше не будет принимать новые задачи, и как только все потоки завершат текущие задачи, ExecutorService отключится. Выполняются все задачи, переданные в ExecutorService до выключения().

  • shutdownNow():

Если вы хотите немедленно закрыть службу ExecutorService, вы можете вызвать метод shutdownNow(). Это попытается немедленно остановить все выполняемые задачи и пропустить все представленные, но не обработанные задачи. Данных о выполнении задач нет. Возможно, они останавливаются, возможно, казнь до конца. Это лучшая попытка усилий.