Ответ 1
Разница, как вы заявили, заключается в том, что один очищает статус прерывания потока, а другой - нет. Поскольку вы уже знаете это, кажется, что вы действительно спрашиваете, важно ли сохранить статус прерывания потока.
Сначала нужно определить, считается ли код проверки статуса прерывания (или обработки InterruptedException
) "владельцем" потока. Если да, то в некоторых ограниченных случаях может быть целесообразным усвоить (или просто не выбросить) InterruptedException
, а также прерванный статус, поскольку владелец реализует политику отмены потока (Goetz, Java Concurrency в Practice, p 143).
Но в подавляющем большинстве случаев, включая Runnable
, данный код не является владельцем потока, а не должен проглатывать статус отмены. В этом случае у вас есть два варианта:
- Оставьте статус прерывания потока очищенным, но введите
InterruptedException
. (Это то, что делаетThread.sleep()
). - Сохранять статус прерывания.
В случае Runnable
вы не можете выставить проверенное исключение, потому что run()
не объявляется для этого. (В свою очередь, я теоретизирую, что он был спроектирован именно так, потому что обычно их не было бы уловить.) Таким образом, ваш единственный выбор - сохранить статус отмены.
Учитывая приведенное выше объяснение, позвольте мне вернуться к вашему прямому вопросу. Прежде всего, если вы хотите проверить статус отмены и сохранить его, проще написать
if (Thread.currentThread().isInterrupted()) doSomething;
чем
if (Thread.interrupted()) {
Thread.currentThread().interrupt();
doSomething;
}
Кроме того, как и в вашем исходном вопросе, если вы использовали Thread.interrupted()
как условие в цикле while
, после разрыва цикла вы не знали бы, завершится ли это, потому что Thread.interrupted()
возвращен true
или какой-либо другой условие изменено или выполняется оператор break
. Поэтому в этом случае использование Thread.currentThread().isInterrupted()
действительно является вашим единственным вариантом. (Конечно, вы могли бы также закодировать цикл таким образом, что единственная причина, по которой он должен был выйти, состоит в том, что поток прерывается, но тогда ваш код будет хрупким, потому что после цикла вы должны повторно прервать поток, и если позже появится кто-то другой и изменил код, чтобы также вырваться из цикла по какой-то другой причине, тогда вы прервали бы поток, когда он не был первоначально прерван.)
К вашему второму вопросу, как утверждали другие, никогда не используйте Thread.currentThread().interrupted()
, потому что он вводит в заблуждение. Поскольку interrupted()
- статический метод, в этом случае компилятор дает вам полезное предупреждение, если вы компилируете с помощью -Xlint
:
предупреждение: статический метод статического класса должен быть присвоен типом имени Thread, а не выражением
Некоторые другие инструменты могут работать аналогично, например Eclipse, которые показывают:
Статический метод прерванный() из типа Thread должен быть доступен статическим способом