В первом случае ("i"), да, спящий поток будет отключен от своего вызова к Thread#sleep()
посредством выброса InterruptedException
. На этом этапе флаг состояния потока, представленный Thread#isInterrupted()
, будет очищен; вызов Thread#isInterrupted()
вернул бы false. Поскольку InterruptedException
находится в полете, сообщение было отправлено всем транзитивным абонентам.
Тогда вызывающие абоненты обязаны перехватить это исключение и сделать одно из двух:
- либо выйдите из текущего потока, либо
- вызов
Thread#interrupt()
в текущем потоке (то есть Thread.currentThread().interrupt()
)
Когда вы говорите, что поток "t1" находится "все еще в состоянии сна, ожидания или соединения", это может произойти только после первоначального вызова Thread#sleep()
через InterruptedException
, если он перехватил исключение, проигнорировал его и снова вызвал некоторый метод блокировки, например Thread.sleep()
, прежде чем поток "t2" сможет его прервать во второй раз.
Если поток "t2" должен был снова прервать поток "t1" , в то время как "t1" в настоящее время заблокирован при прерывании вызова метода , вызов "t1" снова завершится с InterruptedException
. В противном случае флаг прерывания потока будет установлен для последующего обнаружения.
Каждый раз, когда вы вызываете Thread#interrupt()
, статус прерывания этого целевого потока будет установлен на «истина», что означает, что поток был прерван с момента получения статуса прерывания последний очищен. В следующий раз, когда прерванный поток попытается выполнить блокирующий вызов прерываемого метода, состояние прерывания потока будет очищено, и метод сгенерирует InterruptedException
.
Обратите внимание, что очистка статуса прерывания , подобного этому, не приводит к потере информации до тех пор, пока сразу же после очистки следует бросок InterruptedException
. Брошенный InterruptedException
лучше всего интерпретировать как «Этот поток имеет свой статус прерывания , установленный в какой-то момент раньше, и теперь ваша ответственность - реагировать и, как правило, предупреждать последующих абонентов о предполагаемом прерывании». Вы достигаете последней цели, вызывая Thread#interrupt()
после перехвата InterruptedException
, восстанавливая статус прерывания , чтобы другие могли его увидеть.
См. Книгу Java-параллелизм на практике для более авторитетного описания этого протокола.