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

Предположим, что поток t1 работает (то есть не находится в состоянии ожидания, ожидания или соединения). Другой поток t2 прерывает t1. Javadoc сообщает, что статус прерывания t1 будет установлен.

Давайте предположим, что t1 переходит в состояние сна, ожидания или присоединения позже. Что происходит?

i) Поток t1 автоматически поднимается с InterruptedException, поскольку он имеет прерванный статус?

Давайте предположим, что t1 все еще находится в состоянии сна, ожидания или соединения. Давайте представим, что t2 снова прерывает t1:

ii) Поднят ли поток t1 с InterruptedExecution или ему нужно очистить свой статус прерывания с помощью вызова сначала interrupted()?

Есть ли официальная позиция по Java на этом? Спасибо.

Ответы [ 2 ]

2 голосов
/ 24 ноября 2011

В первом случае ("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-параллелизм на практике для более авторитетного описания этого протокола.

1 голос
/ 24 ноября 2011

Проверка прерванного состояния потока очищает флаг состояния;то есть код, который вызывает InterruptedException, очищает состояние, как ваш собственный код, который вручную отбирает состояние.

...