Прерывание потока во время его работы; Каково влияние следующего прерывания?
Предположим, что поток t1 работает (то есть не находится в состоянии ожидания, ожидания или соединения). Другой поток t2 прерывает t1. Javadoc говорит, что статус прерывания t1 будет установлен.
Давайте предположим, что t1 засыпает, ждет или присоединяется к статусу позже. Что просходит?
i) Поток t1 автоматически поднимается с InterruptedException
так как у него был прерванный статус?
Давайте предположим, что t1 все еще находится в состоянии сна, ожидания или соединения. Давайте представим, что t2 снова прерывает t1:
II) нить T1 поднимается с InterruptedExecution
или ему нужно очистить свой статус прерывания с помощью вызова interrupted()
первый?
Есть ли официальная позиция по Java на этом? Благодарю.
2 ответа
В первом случае ("i") да, спящий поток будет отключен от вызова Thread#sleep()
в порядке InterruptedException
быть брошенным На этом этапе флаг состояния потока представлен Thread#isInterrupted()
будет очищено; призвание Thread#isInterrupted()
вернул бы ложь. Так как 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 Concurrency in Practice для более авторитетного описания этого протокола.
Проверка прерванного состояния потока очищает флаг состояния; то есть код, который вызывает InterruptedException
очищает состояние, как ваш собственный код, который вручную проверяет состояние.