WAIT和BLOCKED线程状态之间的区别

Mor*_*ive 94 java multithreading block wait

线程状态WAIT和线程状态BLOCKED之间有什么区别?

Thread.State文档:


阻止等待监视器锁定的线程处于此状态.

正在
等待另一个线程无限期地执行特定操作的线程处于此状态

没有解释给我的区别.

Fla*_*vio 84

差异相对简单.

在该BLOCKED状态中,线程即将进入synchronized块,但是当前synchronized在同一对象的块内运行另一个线程.然后第一个线程必须等待第二个线程退出其块.

在该WAITING状态中,线程正在等待来自另一个线程的信号.这通常通过调用Object.wait()或发生Thread.join().然后线程将保持此状态,直到另一个线程调用Object.notify()或死亡.

  • 最好补充一点,当一个线程从 `WAITING` 状态移动时,它必须首先进入 `BLOCKED` 状态,直到它可以获得与它正在等待的对象关联的锁。 (4认同)
  • [`Thread.State`](https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.State.html)的Java8文档说:“ ...这些状态是虚拟机不能反映任何操作系统线程状态的状态。” 换句话说,JVM不在乎正在运行Java代码的线程,正在等待系统调用返回的线程或正在等待时间片的线程之间的区别。就JVM而言,这些全都是“ RUNNABLE”。 (3认同)
  • 说只有线程本身可以使它进入等待状态,这是正确的吗?线程B能否使线程A进入等待状态? (2认同)

Ank*_*sal 72

一旦调用wait()了Object,线程就会进入等待状态.这称为等待国.一旦线程到达等待状态,它将需要等待一些其他线程notify()notifyAll()对象.

一旦通知此线程,它将无法运行.可能是其他线程也被通知(使用notifyAll())或第一个线程尚未完成其工作,因此它仍然被阻塞,直到它有机会.这称为阻塞状态.

一旦其他线程离开并且这个线程有机会,它就会移动到Runnable状态,之后它就是基于JVM线程机制的合格拾取工作并转移到运行状态.

  • 对于所有那些,谁想知道为什么大多数(全部?)在Web声明中找到的状态图,notify()/ notifyAll()导致RUNNABLE而不是BLOCKED:http://stackoverflow.com/questions/28378592/java -thread-状态转变等待到阻塞的或可运行 (5认同)
  • 您之所以解释得更好,是因为您解释了一个线程到达这两个状态的顺序,这比单独解释两个状态中的每个状态要清晰得多(这是通过“大于五个”的答案完成的) (2认同)
  • 您的回答很好,但并没有完全说明您可以在任何时候尝试获取锁时进入阻塞状态。它与信号/通知没有任何关系。 (2认同)

Nat*_*hes 17

阻塞和等待状态之间的重要区别是对调度程序的影响.处于阻塞状态的线程是争用锁定的waitset的一部分; 该线程仍然算作调度程序需要服务的东西,可能会考虑到调度程序决定给出运行线程的时间.

一旦线程处于等待状态,它对系统施加的压力就会最小化,并且调度程序不必担心它.它会一直处于休眠状态,直到收到通知为止.除了它保持OS线程占用的事实之外,它完全没有用.

这就是为什么使用notifyAll不太理想,它会导致一堆以前很高兴休眠的线程在系统上没有负载被唤醒,其中大多数线程将阻塞,直到他们可以获得锁定,找到它们的条件等待不是真的,回去等待.最好只通知那些有可能取得进展的线程.

(使用ReentrantLock而不是内部锁定允许您为一个锁定具有多个条件,以便您可以确保通知的线程是在等待特定条件的线程,避免在线程获得通知的情况下丢失通知错误它无法作用的东西.)

  • 如果应该避免这种行为,则可以使用“notify”。但仅供那些认为“通知”总是更好的人参考。如果您的应用程序由于“丢失信号”而应该在没有类似死锁的情况下继续进行(如果您的应用程序有可能处于这种情况,并且如果发生这种情况,您的应用程序将无法按您的预期工作),则可以使用“notifyAll” “(此处,预期线程错过了信号,因为信号到达了非预期线程的其他线程)请参阅/sf/answers/223043551/ (2认同)

小智 14

解释线程转储的简化透视图:

  • 等待 -我等着被赋予了一些工作,所以我现在正处于闲置状态.
  • 阻止 - 我正忙着努力完成工作,但另一个线程阻碍了我,所以我现在闲着.
  • RUNNABLE ...(本机方法) - 我调用了一些本机代码(尚未完成),所以就JVM而言,你是RUNNABLE而且它无法提供任何进一步的信息.一个常见的例子是用C编码的本机套接字监听器方法,它实际上在等待任何流量到达,所以我现在正在闲置.在这种情况下,这可以看作是一种特殊的WAIT,因为我们实际上并没有RUNNING(没有CPU刻录),但你必须使用OS线程转储而不是Java线程转储才能看到它.