Переход состояния потока Java, ОЖИДАНИЕ БЛОКИРОВАНА или ВЫПОЛНЕНО?
Кажется, что существует несоответствие между консенсусом SO и почти каждой диаграммой состояния потоков Java в Интернете; в частности, относительно перехода состояния потока из WAITING
после notify()
или же notifyAll()
вызывается...
- ОЖИДАНИЕ никогда не идет прямо в RUNNABLE
- Поток ждет, пока не получит уведомление... Затем он будет заблокирован...
- Как только этот поток уведомлен, он не будет работать... Это... Заблокированное состояние.
Таким образом, концепция SO: поток переходит от WAITING
в BLOCKED
после вызова notify()
или же notifyAll()
; диаграмма ниже иллюстрирует этот переход зеленым цветом.
Вопрос
Почему большинство диаграмм состояний в Интернете иллюстрируют переход от WAITING
в RUNNABLE
не BLOCKED
? Изображение в красном показывает неправильный переход; я что-то пропустил?
4 ответа
Любая диаграмма, которая показывает notify
неправильный вызов переноса потока из ОЖИДАНИЯ в RUNNABLE (или использование невыясненного ярлыка). Как только нить пробуждается от notify
(или даже из-за ложного пробуждения) ему необходимо снова заблокировать монитор объекта, на котором он ожидал. Это BLOCKED
государство.
Состояние потока для потока, заблокированного в ожидании блокировки монитора. Поток в заблокированном состоянии ожидает блокировки монитора, чтобы войти в синхронизированный блок / метод или повторно войти в синхронизированный блок / метод после вызова
Object.wait
,
Это объясняется в Javadoc Object#notify()
:
Пробужденный поток не сможет продолжить работу, пока текущий поток не снимет блокировку этого объекта.
а также Object#wait()
Затем поток ожидает, пока не получит право владения монитором, и возобновит выполнение.
Поток в состоянии ОЖИДАНИЯ переходит в состояние БЛОК, пока он не получит монитор путем уведомления и не станет RUNNABLE.
То же самое относится к TIMEDWAITING, оно переходит в состояние BLOCK, если монитор удерживается каким-либо другим потоком, даже если указанное время прошло.(ваша диаграмма должна быть исправлена)
Я фокусируюсь на проблеме в последнее время.
как говорится в документе Oracle Thread.State, мы можем использовать LockSupport.park(), чтобы перевести текущий поток в состояние "WAITING" или "TIMED_WAITING".
поэтому, когда вы попытаетесь использовать LockSupport.unpark (), указанный поток вернется к "RUNNABLE" из "WAITING" / "TIMED_WAITING". (Я не уверен, пройдет ли он через состояние "ЗАБЛОКИРОВАНО")
Стоит отметить, что это также верно для метода во время состояния, в то время как в
lock.wait()
метод.
Thread.interrupt()
метод сначала сделает
WAITING
нить
BLOCKED
с
isInterrupted
флаг установлен в значение true, и только после повторного получения блокировки прерванный поток сможет бросить
InterruptedException
(это очевидно, так как он не может обрабатывать исключение, продолжая выполнение без монопольной блокировки ранее). (пример здесь )
Просто сказать
Всегда
WAITING -> BLOCKED
чтобы иметь возможность снова конкурировать за блокировку, а после этого получить ее в конце концов и запустить ее код
RUNNABLE
.