InterruptedException внутри ExecutorService

Должны ли мы устанавливать флаг прерывания при перехвате InterruptedException внутри задачи, управляемой ExecutorService? Или мы должны просто проглотить InterruptedException?

Пример:

final ExecutorService service = ...;
final Object          object  = ...;

service.submit(() -> {
    try {
        while (!condition) {
            object.wait();
        }
    } catch (final InterruptedException exception) {
        Thread.currentThread().interrupt(); // yes or no?
    }
});

person Community    schedule 01.04.2016    source источник
comment
Это зависит от контекста и требований. Эмпирическое правило: не глотайте, если вы не знаете, что делаете, и у вас нет веских причин.   -  person Ole V.V.    schedule 01.04.2016
comment
Внутри ExecutorService в чем разница между проглатыванием и не проглатыванием исключения? Как ведет себя ExecutorService в обоих случаях?   -  person    schedule 01.04.2016


Ответы (2)


В задаче, отправленной на ExecutorService, получение прерывания является сигналом к ​​отмене выполнения задачи. Итак, в вашем примере кода ответ «нет», не устанавливайте прерывание снова.

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

Своевременное завершение работы исполнителя зависит от задач, завершающихся в ответ на прерывание; это не зависит от задач, восстанавливающих состояние прерывания.

person erickson    schedule 01.04.2016
comment
Обратите внимание, что InterruptedException происходит не только тогда, когда исполнителя просят .shutdown(). Это также происходит, если соответствующий Future<?> запрашивает .cancel(true). Будет ли ExecutorService вести себя одинаково в обоих случаях (глотать или нет)? - person ; 02.04.2016
comment
@JasarTolio Да, он ведет себя так же. В своем ответе я говорил в первую очередь о Future.cancel() звонках; резкое завершение работы можно рассматривать как запрос cancel() для любых отправленных задач. Единственный эффект прерывания рабочего потока ThreadPoolExecutor состоит в том, чтобы заставить его проснуться и проверить состояние исполнителя. Если это состояние на самом деле не изменилось, оно вернется к poll() или take() следующей задаче из рабочей очереди. - person erickson; 02.04.2016
comment
Четкий ответ! Благодарю вас! - person ; 02.04.2016

Как советует эта хорошая статья, никогда не глотайте InterruptedException.

person Matteo Baldi    schedule 01.04.2016
comment
Статья довольно старая и не учитывает современный пакет Java Concurrent. Идеи, конечно, те же, но контекст может быть другим, так как ExecutorService отвечает. - person ; 02.04.2016