Java-等待并通知所有

Java-等待并通知所有,java,wait,Java,Wait,在未等待的对象上调用notifyAll方法时会发生什么?应该有例外还是正常情况?这是完全正常的。您只能通知在一个监视器上等待的所有人。其他人都不感兴趣。调用notifyAll的对象只是其他人正在等待的监视器。如果没有人在等待,则不必通知任何人,如您在此处所见,对未等待对象调用notifyAll()不会产生任何效果 只有等待的对象才会得到通知。Object.wait()阻塞直到超时或通知-所以问题仍然是,您认为非等待对象将如何或为什么得到通知?这毫无意义。对象是“等待的”,而不是等待本身。线程是正

在未等待的对象上调用notifyAll方法时会发生什么?应该有例外还是正常情况?

这是完全正常的。您只能通知在一个监视器上等待的所有人。其他人都不感兴趣。调用notifyAll的对象只是其他人正在等待的监视器。如果没有人在等待,则不必通知任何人,如您在此处所见,对未等待对象调用notifyAll()不会产生任何效果


只有等待的对象才会得到通知。Object.wait()阻塞直到超时或通知-所以问题仍然是,您认为非等待对象将如何或为什么得到通知?这毫无意义。

对象是“等待的”,而不是等待本身。线程是正在等待的线程。如果没有人在等待,没有人会醒来,也不会有什么特别的事情发生。

完全正常的情况

假设您有一个队列,其中生产者线程将元素放入其中,消费者线程从中移除元素


现在,使用者可能已经清空了队列,仍然在处理,因此没有人在等待队列变为非空。现在,生产者将一个新元素添加到队列中。如果消费者正在等待,他必须调用notifyAll()唤醒消费者。添加额外的逻辑来检查是否有人在等待,并且在这种情况下只调用notifyAll()会给场景增加相当大的复杂性(而且非常容易失败)-每次只调用notifyAll()要容易得多。

我可能只是在吹毛求疵;-)认为notifyAll上的线程从“等待”状态变为“运行”状态可能不是严格正确的;至少要注意的是,通知线程所做的第一件事就是重新标记监视器锁。由于只有一个通知线程可以抓取它,其他线程将被阻止BLOCKEDThread.State.BLOCKED)是线程状态。但是阻塞与等待不同,因为被阻塞的线程不需要另一个notify()信号来恢复。[我知道有虚假的唤醒,但对于某些JVM实现,情况可能正好相反-错过通知?]


对象不等待或被通知-线程等待。在监视器对象上调用notifyAll()而不知道是否有线程在等待它,这是完全可能和正常的。例如,在具有队列的生产者/消费者场景中,当生产者向队列添加新元素并通知所有正在等待的消费者(即无)时,消费者可能已清空队列并仍在忙于处理关于这一点。当警报响起但没有人听到时会发生什么?将线程从等待放到notifyAll上运行可能不是严格正确的做法,或者至少在没有警告的情况下,通知线程所做的第一件事就是重新标记监视器锁。由于只有一个通知线程可以抓取它,其他线程将被阻止。但是阻塞与等待不同,因为被阻塞的线程不需要另一个notify()信号。
public class HellBoy {
    public static class MyThread extends Thread {
        static final public Object sharedLock = new Object();

        public void run() {
            synchronized (sharedLock) {
                System.out.println("Gonna wait...");
                try {
                    sharedLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Woken up but sleeping with the lock");
                try {
                    Thread.sleep(2500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("exiting and unlocking");
            }
        }
    }

    public static void main(String[] args) throws Exception {
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        Thread.sleep(200);
        synchronized (MyThread.sharedLock) {
            MyThread.sharedLock.notifyAll();
        }
    }
}