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

时间:2015-02-07 04:36:01

标签: java multithreading thread-state java-threads

SO共识与互联网上几乎所有Java线程状态图之间似乎存在差异;具体来说,关于在调用WAITINGnotify()后来自 notifyAll()的线程状态转换 ...

  • 等待never直接转到RUNNABLE
  • 线程正在等待,直到通知......然后它becomes阻止...
  • 一旦通知此线程,它就会will not be runnable ...这是......阻止状态。

因此,关于SO的共识是:在调用WAITINGBLOCKED之后,线程从notify()转换为notifyAll();下图说明了绿色的这种转变。

问题

为什么大多数state diagrams on the web都说明了从WAITINGRUNNABLE的过渡,而不是BLOCKED?红色描绘显示错误的过渡;我错过了什么吗?

enter image description here

4 个答案:

答案 0 :(得分:14)

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

  

线程的线程状态被阻塞等待监视器锁定。一个帖子   处于阻塞状态正在等待监视器锁定进入   同步块/方法或之后重新输入同步块/方法   致电Object.wait

Object#notify()

的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