Можно ли игнорировать InterruptedException, если никто не вызывает interrupt ()?

Если я создаю свой собственный поток (т. е. не threadpool) и где-то я вызываю sleep или любой другой прерываемый метод, можно ли игнорировать InterruptedException Если я знаю, что никто другой в коде не делает прерывание в потоке.

другими словами, если поток должен жить до тех пор, пока JVM, то есть поток не прерывается, можно с уверенностью предположить, что InterruptedException будет никогда вызывается и, следовательно, исключение можно проглотить?

8 ответов


игнорирование проверенного исключения никогда не считается безопасным.
На данный момент это может быть нормально, но если другой программист расширит ваш код, он будет ожидать стандартное поведение: поток, реагирующий на вызов прерывания.
Также пустой блок catch опасен в этом случае, так как JVM удаляет прерванный флаг, и он обязательно должен быть установлен снова с

Thread.currentThread().interrupt();

в блоке catch. На мой взгляд, это минимальный улов реализации InterruptedExceptions. Проверка на isInterrupted флаг в цикле тоже не больно.
Это немного накладных расходов по сравнению с хлопотами вашего будущего программиста, который ищет день или два для неожиданного поведения потока, поскольку вы, возможно, немного выросли.

если вы чувствуете, что читаемость вашего кода страдает от этих реализаций catch, вы можете реализовать свой собственный safeSleep utility метод, который заботится о Exceptions и устанавливает флаг правильно.

С другой стороны, InterruptedException не выбрасывается самим JVM в случае сбоя оборудования,это пользователь указал Exception только. Итак, если вы не распространяете свой Threadссылки, не будет никаких других Threads, которые могут вызвать Thread.interrupt() на нем. вот это технически. но вы не должны недооценивать человеческий фактор и эволюцию ваших программ.
Edit: As ruakh указал, на самом деле есть способ получить Threadссылки и таким образом, чтобы назначить Thread.interrupt() звонок. Таким образом, разработчику в heat, возможно, даже не придется смотреть на класс, который реализует ваш бесперебойный Thread. На мой взгляд, это еще одна причина, чтобы реализовать правильную обработку исключений.
другое дело: если вы не бросаете Exception, регистрируя такое событие на уровне за пределами INFO может быть хорошим выбором.


вместо того, чтобы проглотить его, если вы так уверены, что это никогда не произойдет, вы можете врезаться вместо того, чтобы игнорировать его. Например, бросьте Error (или RuntimeException):

try {
    Thread.sleep(1000);
} catch (InterruptedException e) {
    throw new Error(e);
}

С Javadocs для ошибки:

ошибка-это подкласс Throwable, который указывает на серьезные проблемы, которые разумное приложение не должно пытаться поймать. Большинство таких ошибок-ненормальные условия.

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

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


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

минимум, что вы должны сделать, это:

catch(InterruptedException ex) {
  throw new AssertionError(ex);
}

это гарантирует, что всякий раз, когда ваше утверждение, что это никогда не произойдет, неправильно, вы заметите. Этот шаблон также применяется к другим неожиданным исключениям, например IOException когда вы знаете, что цель OutputStream - это ByteArrayOutputStream или Appendable of a Formatter должно быть StringBuilder, etc.


кстати, есть альтернатива Thread.sleep не требуется иметь дело с InterruptedException на всех:

LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(timeInMillis));

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


книга, которую я все еще считаю Библией по этим вопросам, Goetz et al. параллелизм Java на практике говорит следующие важные биты в главе 7 (в значительной степени тот же материал находится в Гетце статье, который имеет преимущество быть свободным, но книга немного более ясна по некоторым пунктам.)

прерывание-это механизм сотрудничества. Одна нить не может заставить другую остановись и сделай что-нибудь. когда поток A прерывает поток B, A просто просит, чтобы B прекратил то, что он делает, когда он достигает удобной точки остановки-если он чувствует, что это так.

[...]

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

Да, да, вы можете "проглотить" InterruptedException при обстоятельствах, которые вы изложили.

также важный момент в книге:

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

таким образом, вы можете выбрать свою собственную политику, как "сбой" с RuntimeException, AssertionError, просто регистрируя его как предупреждение или полностью игнорируя прерывание, пока вы документируете эту проблему для тех, кому еще может понадобиться знать. Что лучше зависит от того, что ваша нить действительно работает, и вы не предоставили никаких подробностей об этом. Например, если он работает на ракете [скажем, делает контроль ориентации], вы не хотите разбить JVM / rocket только потому, что другой программист [который может даже не работать в той же компании, что и вы, например, он написал какую-то библиотеку, которую вы называете] забыл об определенном контракте где-то в своем коде и сбрасывает безопасно игнорируемое исключение на ваш: "исключение, которое произошло, было вызвано не случайным сбоем, а конструкцией ошибка."


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


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

catch (InterruptedException e) { 
     // Restore the interrupted status
     Thread.currentThread().interrupt();
 }

Если вы prompty выходите из потока после улова.

здесьстатья о работе с InterruptedExceptions.


если поток должен жить до тех пор, пока JVM, то есть поток не прерывается, можно ли с уверенностью предположить, что InterruptedException будет никогда быть брошенным и, следовательно, исключение можно проглотить?

Я понимаю вашу боль, распространение шаблонных блоков try-catch без бизнес-ценности вредит коду.

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

если вы работаете с Java 8, у вас есть другой вариант, описанный здесь: оберните свой код внутри uncheckCall(() -> { ... }) блок. Это позволяет блоку кода бросить InterruptedException без объявления. Как объяснено в связанном ответе, это должно быть обработано с крайней осторожностью, но оно имеет потенциал сделать ваш код достаточно чистым.


Я думаю, игнорирование InterruptedException безопасно или нет, зависит от того, что вы делаете в этом потоке. Если есть какой-либо сценарий, когда нежелательное прерывание вашего потока может оставить систему или любой ресурс в нежелательном состоянии (грязный, заблокированный, не освобожденный, который может вызвать утечку ресурса), то его ваша ответственность за обработку InterruptedException, и вы не должны игнорировать его. Это зависит от вас, Хотите ли вы, чтобы ваш поток прерывался или нет.

другими словами Механизм прерывания в основном используется для реализации политики отмены и очистки задач. У вас нет ничего, чтобы очистить в задаче или у вас нет каких-либо конкретных политик отмены задачи, игнорирование IntrruptedException может не звучать политически корректно, но в порядке.