SO共识与互联网上几乎所有Java线程状态图之间似乎存在差异;具体来说,关于在调用WAITING
或notify()
后来自 notifyAll()
的线程状态转换 ...
因此,关于SO的共识是:在调用WAITING
或BLOCKED
之后,线程从notify()
转换为notifyAll()
;下图说明了绿色的这种转变。
为什么大多数state diagrams on the web都说明了从WAITING
到RUNNABLE
的过渡,而不是BLOCKED
?红色描绘显示错误的过渡;我错过了什么吗?
答案 0 :(得分:14)
任何显示notify
调用将线程从WAITING带到RUNNABLE的图表都是错误的(或使用未明确的快捷方式)。一旦线程从notify
唤醒(甚至从虚假的唤醒中唤醒),它需要重新锁定它正在等待的对象的监视器。这是BLOCKED
州。
的javadoc解释了这一点线程的线程状态被阻塞等待监视器锁定。一个帖子 处于阻塞状态正在等待监视器锁定进入 同步块/方法或之后重新输入同步块/方法 致电
Object.wait
。
唤醒的线程将无法继续直到当前 线程放弃对此对象的锁定。
然后线程等待,直到它可以重新获得监视器的所有权 并恢复执行。
答案 1 :(得分:1)
线程处于等待状态进入 BLOCK 状态,直到它通过notify获取监视器并变为 RUNNABLE 。
同样适用于 TIMEDWAITING ,它会进入 BLOCK 状态,如果监视器被某个其他线程保留,即使已经过了指定的时间。(你的图表需要纠正)
答案 2 :(得分:0)
我最近关注这个问题。
正如Oracle文档Thread.State所说,我们可以使用LockSupport.park()将当前线程置于'WAITING'或'TIMED_WAITING'状态。
所以当你尝试LockSupport.unpark()时,指定的线程将从'WAITING'/'TIMED_WAITING'返回'RUNNABLE'。 (我不确定它是否会通过'阻塞'状态)
答案 3 :(得分:0)
值得一提的是,Thread.interrupt()
方法在 WAITING
状态和 lock.wait()
方法中也是如此。
Thread.interrupt()
方法将首先使 WAITING
线程 BLOCKED
带有 isInterrupted
标志设置为 true,并且只有在重新获取锁后被中断的线程才能抛出 {{1} (这是显而易见的,因为它无法处理异常,通过在没有排他锁之前继续执行)。 (example here)
简单的说
总是 InterruptedException
能够再次竞争锁,然后最终获取它并运行它的代码 WAITING -> BLOCKED
。