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

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

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

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

4b9b3361

Ответ 1

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

Thread.currentThread().interrupt();

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

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

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

Ответ 2

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

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

Из Javadocs for Error:

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

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

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

Ответ 3

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

Минимум, который вы должны сделать, это:

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

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


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

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

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

Ответ 4

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

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

[...]

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

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

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

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

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

Ответ 5

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

Ответ 6

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

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

если вы не пропустите выход из потока после catch.

Здесь статья о работе с InterruptedException s.

Ответ 7

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

Я понимаю вашу боль, распространение блоков шаблонов tryplate, не имеющих ценности для бизнеса, повреждает код.

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

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

Ответ 8

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

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