Выключение ExecutorService

Согласно документации , когда вызывается shutdown(), будут выполнены любые задачи, которые уже были отправлены (я полагаю, через submit() или execute). Когда вызывается shutdownNow(), исполнитель останавливает все задачи, ожидающие обработки, а также пытается остановить активное выполнение задач.

Что я хотел бы уточнить, так это точное значение «ожидания обработки». Например, у меня есть исполнитель, и я вызываю execute() для некоторого количества Runnable объектов (предположим, что все эти объекты эффективно игнорируют прерывания). Я знаю, что если я сейчас вызову shutdown, все эти объекты закончат выполнение, независимо от того.

Однако, если я вызову shutdownNow в этот момент, будет ли это иметь тот же эффект, что и вызов shutdown? Или часть объектов не выполняется? Другими словами, если я хочу, чтобы исполнитель завершил работу как можно быстрее, лучше ли мне всегда вызывать shutdownNow(), даже если Runnables передается исполнителю, и все они эффективно игнорируют прерывания?


person b_pcakes    schedule 18.11.2015    source источник


Ответы (3)


Что я хотел бы уточнить, так это точное значение «ожидания обработки».

Это означает все задачи, метод run() которых еще не был вызван (исполнителем).

Если я вызову shutdownNow в этот момент, будет ли это иметь тот же эффект, что и вызов shutdown?

No.

Или возможно, что часть объектов не будет выполнена?

Это правильно.

Другими словами, если я хочу, чтобы исполнитель завершил работу как можно быстрее, лучше ли мне всегда вызывать shutdownNow(), даже если Runnables, переданные исполнителю, эффективно игнорируют прерывания?

Это правильно.

А еще лучше перекодировать Runnables, чтобы обращать внимание на прерывания... или поставить тайм-аут на выключение...

person Stephen C    schedule 18.11.2015
comment
Одно быстрое дополнение: если мой поток блокируется в вызове executor.awaitTermination() и меня прерывают, что именно происходит? Мне все равно придется звонить shutdown/shutdownNow? - person b_pcakes; 18.11.2015
comment
1) вызов awaitTemination() вызовет InterruptedException вызывающему. Но помните, что это происходит, когда прерывается ожидающий поток, а не любой поток, принадлежащий службе-исполнителю. 2) Если вы хотите, чтобы исполнитель отключился, то да. - person Stephen C; 18.11.2015

Допустим, у вас есть этот сказочный Runnable, который нельзя прервать в течение 10 секунд после запуска:

Runnable r = new Runnable() {
    @Override
    public void run() {
        long endAt = System.currentTimeMillis() + 10000;
        while (System.currentTimeMillis() < endAt);
    }
};

И у вас есть исполнитель всего с 1 потоком, и вы планируете выполнение 10 раз:

ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < 10; i++)
    executor.execute(r);

И вот вы решаете позвонить shutdown:

  • Исполнитель продолжает работу в течение полных 10 x 10 секунд, и все запланированное будет выполнено. Задачи не видят, что вы закрываете их исполнителя. shutdown можно использовать, если вам нужен "короткоживущий" исполнитель только для нескольких задач. Вы можете сразу же позвонить shutdown, и он будет очищен позже.

Альтернативно shutdownNow():

  • Занимает 10 секунд. Предпринимается попытка прервать уже запущенную задачу, но это, очевидно, не имеет никакого эффекта, поэтому она продолжает выполняться. Остальные 9 задач, которые все еще ждали в очереди, «отменяются» и возвращаются вам в виде списка, чтобы вы могли что-то с ними сделать, например запланировать их позже. Также может занять 0 секунд, если первая задача еще не запущена. Вы получите все задачи обратно. Этот метод используется всякий раз, когда вы хотите прервать выполнение всего исполнителя.
person zapl    schedule 18.11.2015

API для метода shutdownNow говорит, что:

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

источник

person Caffeinated    schedule 18.11.2015