Прерывание потока во время его работы; Каково влияние следующего прерывания?

Предположим, что поток 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 очищает состояние, как ваш собственный код, который вручную проверяет состояние.

Другие вопросы по тегам