Короткая версия:
Это известная лучшая практика никогда
использовать Thread.interrupt ()?
номер
Можете ли вы предоставить
доказательства того, почему он сломан / багги,
и не должен использоваться для письма
Надежный многопоточный код?
Верно обратное: это критично для многопоточного кода.
См. Пример листинга 7.7 в Параллелизм Java на практике .
Более длинная версия:
Здесь мы используем этот метод в одном конкретном месте: обработка InterruptedExceptions
. Это может показаться немного странным, но вот как это выглядит в коде:
try {
// Some code that might throw an InterruptedException.
// Using sleep as an example
Thread.sleep(10000);
} catch (InterruptedException ie) {
System.err.println("Interrupted in our long run. Stopping.");
Thread.currentThread().interrupt();
}
Это делает для нас две вещи:
- Это позволяет избежать употребления исключения прерывания. Обработчики IDE-автоматических исключений всегда предоставляют вам что-то вроде
ie.printStackTrace();
и небольшую фразу "TODO: здесь нужно что-то полезное!" комментарий.
- Восстанавливает состояние прерывания, не вызывая проверенное исключение для этого метода. Если в сигнатуре метода, которую вы реализуете, нет предложения
throws InterruptedException
, это другой вариант для передачи этого прерванного статуса.
Комментатор предложил, чтобы я использовал непроверенное исключение ", чтобы заставить поток умирать". Это предполагает, что у меня есть предварительные знания, что резкое уничтожение потока - это то, что нужно делать. Я не.
Чтобы процитировать Брайана Гетца из JCIP на странице перед перечисленным выше списком:
Задача не должна предполагать ничего о политике прерывания ее
выполнение потока, если он явно не предназначен для работы в
служба с определенной политикой прерывания.
Например, представьте, что я сделал это:
} catch (InterruptedException ie) {
System.err.println("Interrupted in our long run. Stopping.");
// The following is very rude.
throw new RuntimeException("I think the thread should die immediately", ie);
}
Я бы объявил, что, независимо от других обязательств остальной части стека вызовов и связанного состояния, этот поток должен прекратиться прямо сейчас. Я бы попытался обойти все остальные блоки catch и указать код очистки, чтобы сразу перейти к смерти потока. Хуже того, я бы использовал статус прерванного потока. Теперь вышестоящей логике пришлось бы деконструировать мое исключение, чтобы попытаться выяснить, была ли логическая ошибка программы или я пытаюсь скрыть проверенное исключение внутри скрывающей оболочки.
Например, вот что немедленно должны были сделать все остальные в команде:
try {
callBobsCode();
} catch (RuntimeException e) { // Because Bob is a jerk
if (e.getCause() instanceOf InterruptedException) {
// Man, what is that guy's problem?
interruptCleanlyAndPreserveState();
// Restoring the interrupt status
Thread.currentThread().interrupt();
}
}
Прерванное состояние важнее любого конкретного InterruptException
. Конкретный пример почему см. В javadoc для Thread.interrupt () :
Если этот поток заблокирован при вызове wait (), wait (long),
или методы wait (long, int) класса Object или join (),
методы join (long), join (long, int), sleep (long) или sleep (long, int), методы
этого класса, то его статус прерывания будет очищен, и он будет
получить InterruptedException.
Как вы можете видеть, более одного InterruptedException может быть создано и обработано, так как запросы на прерывание обрабатываются, но только если это состояние прерывания сохраняется.