SO共识和网上几乎所有的Java线程状态图似乎都有出入;具体来说,关于从 WAITING
之后notify()
或被notifyAll()
调用的线程状态转换......
所以对 SO 的共识是:一个线程在调用or后从WAITING
到; 下图以绿色说明了这种转变。BLOCKED
notify()
notifyAll()
问题
为什么网络上的大多数状态图都说明了从WAITING
到的转换RUNNABLE
,而不是BLOCKED
?红色表示不正确的过渡;我错过了什么吗?
SO共识和网上几乎所有的Java线程状态图似乎都有出入;具体来说,关于从 WAITING
之后notify()
或被notifyAll()
调用的线程状态转换......
所以对 SO 的共识是:一个线程在调用or后从WAITING
到; 下图以绿色说明了这种转变。BLOCKED
notify()
notifyAll()
为什么网络上的大多数状态图都说明了从WAITING
到的转换RUNNABLE
,而不是BLOCKED
?红色表示不正确的过渡;我错过了什么吗?
任何显示notify
将线程从 WAITING 变为 RUNNABLE 的调用的图表都是错误的(或使用了未明确的快捷方式)。一旦线程从notify
(甚至是虚假唤醒)中唤醒,它需要重新锁定它正在等待的对象的监视器。这就是BLOCKED
状态。
线程阻塞等待监视器锁的线程状态。处于阻塞状态的线程正在等待监视器锁进入同步块/方法或调用后重新进入同步块/方法
Object.wait
。
这在以下的 javadoc 中进行了解释Object#notify()
:
在当前线程放弃对该对象的锁定之前,被唤醒的线程将无法继续。
然后线程等待直到它可以重新获得监视器的所有权并恢复执行。
处于WAITING状态的线程进入BLOCK状态,直到它通过 notify 获得监视器并变为RUNNABLE。
同样适用于TIMEDWAITING,它进入BLOCK状态,如果监视器被其他线程持有,即使指定的时间已经过去。(您的图表需要更正)
我最近专注于这个问题。
正如 Oracle 文档Thread.State所说,我们可以使用 LockSupport.park() 将当前线程置于“WAITING”或“TIMED_WAITING”状态。
所以当你尝试LockSupport.unpark()时,指定的线程将从'WAITING'/'TIMED_WAITING'返回到'RUNNABLE'。(我不确定它是否会进入“BLOCKED”状态)
值得一提的是,Thread.interrupt()
method during WAITING
state while in lock.wait()
method 也是如此。
Thread.interrupt()
方法首先将标志设置为true的WAITING
线程BLOCKED
,isInterrupted
只有在重新获得锁之后,被中断的线程才能抛出InterruptedException
(很明显,因为它无法处理异常,所以在没有排他锁的情况下继续执行)。(此处为示例)
简单的说
总是WAITING -> BLOCKED
能够再次竞争锁,然后最终获得它并运行它的代码RUNNABLE
。