如果一个人在谷歌上搜索“notify()和notifyAll()之间的区别”,那么会跳出很多解释(撇开javadoc段落)。这都归结于被唤醒的等待线程的数量:notify()中有一个,notifyAll()中有所有线程。

然而(如果我确实理解了这些方法之间的区别),只有一个线程总是被选择用于进一步的监视采集;第一种情况是VM选择的线程,第二种情况是系统线程调度程序选择的线程。程序员不知道它们的确切选择过程(在一般情况下)。

那么notify()和notifyAll()之间有什么有用的区别呢?我遗漏了什么吗?


当前回答

notify() -从对象的等待集中随机选择一个线程,并将其置于BLOCKED状态。对象的等待集中的其余线程仍然处于WAITING状态。

notifyAll() -将所有线程从对象的等待集移动到BLOCKED状态。使用notifyAll()后,共享对象的等待集中没有剩余线程,因为所有线程现在都处于BLOCKED状态,而不是WAITING状态。

BLOCKED—锁定获取阻塞。 WAITING -等待通知(或阻塞连接完成)。

其他回答

notify() -从对象的等待集中随机选择一个线程,并将其置于BLOCKED状态。对象的等待集中的其余线程仍然处于WAITING状态。

notifyAll() -将所有线程从对象的等待集移动到BLOCKED状态。使用notifyAll()后,共享对象的等待集中没有剩余线程,因为所有线程现在都处于BLOCKED状态,而不是WAITING状态。

BLOCKED—锁定获取阻塞。 WAITING -等待通知(或阻塞连接完成)。

线程有三种状态。

WAIT -线程没有使用任何CPU周期 BLOCKED -线程在试图获取监视器时被阻塞。它可能仍在使用CPU周期 RUNNING -线程正在运行。

现在,当调用notify()时,JVM选择一个线程并将其移动到BLOCKED状态,从而将其移动到RUNNING状态,因为没有竞争监视器对象。

当调用notifyAll()时,JVM选取所有线程并将它们移到BLOCKED状态。所有这些线程都将优先获得对象的锁。能够首先获取监视器的线程将能够首先进入RUNNING状态,依此类推。

看看@xagyg发布的代码。

假设两个不同的线程正在等待两个不同的条件: 第一个线程等待buf.size() != MAX_SIZE,第二个线程等待buf.size() != 0。

假设在某一点buf.size()不等于0。JVM调用notify()而不是notifyAll(),并且通知第一个线程(而不是第二个线程)。

第一个线程被唤醒,检查buf.size(),它可能返回MAX_SIZE,然后返回等待。第二个线程没有被唤醒,继续等待,不调用get()。

摘自Java大师Joshua Bloch在Effective Java第二版中的文章:

“第69项:选择并发实用程序而不是等待和通知”。

我认为这取决于资源是如何生产和消费的。如果同时有5个工作对象,并且您有5个消费者对象,那么使用notifyAll()唤醒所有线程是有意义的,这样每个线程都可以处理1个工作对象。

如果您只有一个可用的工作对象,那么唤醒所有使用者对象来争夺这个对象有什么意义呢?第一个检查可用工作的线程将得到它,所有其他线程将检查并发现它们无事可做。

我在这里找到了一个很好的解释。简而言之:

The notify() method is generally used for resource pools, where there are an arbitrary number of "consumers" or "workers" that take resources, but when a resource is added to the pool, only one of the waiting consumers or workers can deal with it. The notifyAll() method is actually used in most other cases. Strictly, it is required to notify waiters of a condition that could allow multiple waiters to proceed. But this is often difficult to know. So as a general rule, if you have no particular logic for using notify(), then you should probably use notifyAll(), because it is often difficult to know exactly what threads will be waiting on a particular object and why.