Java 线程状态转换,WAITING 到 BLOCKED,还是 RUNNABLE?

Posted

技术标签:

【中文标题】Java 线程状态转换,WAITING 到 BLOCKED,还是 RUNNABLE?【英文标题】:Java thread state transition, WAITING to BLOCKED, or RUNNABLE? 【发布时间】:2015-04-07 08:27:07 【问题描述】:

SO 共识和网上几乎所有的 Java 线程状态图似乎都有出入;具体来说,关于在调用notify()notifyAll() 之后的线程状态转换 WAITING...

WAITING never 直接进入 RUNNABLE 线程一直在等待,直到收到通知...然后它 becomesBLOCKED... 一旦这个线程被通知,它will not be runnable...这是..阻塞状态。

所以对SO的共识是:调用notify()notifyAll()后,线程从WAITING转换为BLOCKED;下图以绿色显示了这种过渡。

问题

为什么大多数state diagrams on the web 说明了从WAITINGRUNNABLE 的转换,而不是BLOCKED?红色表示不正确的过渡;我错过了什么吗?

【问题讨论】:

根据您的评论,我为什么要问绘制图表的人他们并不了解? :-) 我说“不要或没有”。如果你问他们,他们可能会发现他们错了。或者他们可能已经发现了。 所以你是说我的图表比大约 106,000 个 Google 结果更准确?地狱! 如果是这样,TIMED_WAIT 有什么特别之处?为什么直接回到RUNNABLE,而不是转到BLOCKED 如果您需要,还有一些更清晰的答案。 ***.com/q/15680422/2361308 【参考方案1】:

值得一提的是,Thread.interrupt() 方法在WAITING 状态期间,而在lock.wait() 方法中也是如此。

Thread.interrupt() 方法将首先使WAITING 线程BLOCKEDisInterrupted 标志设置为true,并且只有在重新获得锁后被中断的线程才能抛出InterruptedException(这很明显,因为它无法处理异常,通过在没有排他锁的情况下继续执行)。 (example here)

简单来说

总是WAITING -> BLOCKED 能够再次竞争锁,然后最终获得它并运行它的代码RUNNABLE

【讨论】:

【参考方案2】:

处于WAITING状态的线程进入BLOCK状态,直到通过notify获取monitor,变为RUNNABLE

同样适用于 TIMEDWAITING,它进入 BLOCK 状态,如果监视器被其他线程持有,即使指定的时间已经过去。(你的图表需要更正)

【讨论】:

【参考方案3】:

我最近正在关注这个问题。

正如 Oracle 文档 Thread.State 所说,我们可以使用 LockSupport.park() 将当前线程置于“WAITING”或“TIMED_WAITING”状态。

所以当你尝试LockSupport.unpark() 时,指定的线程将从'WAITING'/'TIMED_WAITING' 返回到'RUNNABLE'。 (我不确定它是否会进入 'BLOCKED' 状态)

【讨论】:

我认为LockSupport.unpark()会直接导致指定线程状态由WAITING变为RUNNABLE。【参考方案4】:

任何显示 notify 调用将线程从 WAITING 变为 RUNNABLE 的图表都是错误的(或正在使用未明确的快捷方式)。一旦线程从notify(甚至是虚假唤醒)中唤醒,它需要重新锁定它正在等待的对象的监视器。这是BLOCKED 状态。

线程阻塞等待监视器锁的线程状态。一根线 处于阻塞状态正在等待监视器锁进入 同步块/方法或在之后重新输入同步块/方法 打电话给Object.wait

这在Object#notify()的javadoc中有解释:

被唤醒的线程将无法继续,直到当前 线程放弃对该对象的锁定。

Object#wait()

线程然后等待,直到它可以重新获得监视器的所有权 并继续执行。

【讨论】:

有道理。但是,那么TIMED_WAITING 肯定也是这样吗? 除非它因为sleep(t)而进入TIMED_WAITING状态。 @mystarrocks 根据Thread.State javadoc,WAITING 用于无参数Object#wait,而TIMED_WAITING 用于接受等待时间的过载。是的,这适用于两者。关于sleep,线程不会解锁任何持有的监视器,它在唤醒时仍然拥有它们。

以上是关于Java 线程状态转换,WAITING 到 BLOCKED,还是 RUNNABLE?的主要内容,如果未能解决你的问题,请参考以下文章

Java线程状态及其转换

java线程状态及转换

Java中线程状态的各种转换关系

Java多线程:线程状态探究

Java线程的6种状态转换

实战并发编程 - 06线程在执行过程中的状态是如何流转的