Java - 等待并通知所有

时间:2009-05-06 06:29:46

标签: java wait

在没有等待的对象上调用notifyAll方法时会发生什么?是否有异常或是否正常?

6 个答案:

答案 0 :(得分:8)

正如你在这里看到的,在一个不等待的对象上调用notifyAll()没有任何效果。

alt text

答案 1 :(得分:6)

这是完全正常的。您只能通知在一台显示器上等待的所有人。其他人都不感兴趣。您调用notifyAll的对象只是其他人正在等待的监视器。如果没有人在等待,则无人接收通知

答案 2 :(得分:2)

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

答案 3 :(得分:2)

完全正常的情况。

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

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

答案 4 :(得分:1)

只有等待对象才会收到通知。 Object.wait()阻塞直到超时或通知 - 所以问题仍然是你认为非等待对象会如何或为什么会被通知?没有意义。

答案 5 :(得分:1)

我可能只是分裂头发;-)在notifyAll上将线程从“等待”状态置于“运行”状态可能并不完全正确;至少并非没有警告,通知线程所做的第一件事是重新调整监视器锁定。由于通知线程数量中只有一个可以获取,其他线程将被阻止 BLOCKED Thread.State.Blocked )是线程状态。但是阻塞与等待不一样,因为阻塞的线程不需要另一个notify()信号来恢复。 [嗯,我知道虚假的唤醒,但对于某些JVM实现可能也是如此 - 错过通知?]

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();
        }
    }
}