Java - подожди и уведомь все - PullRequest
5 голосов
/ 06 мая 2009

Что происходит, когда вы вызываете метод notifyAll для объекта, который не ожидает? Должно ли быть исключение или это нормальная ситуация?

Ответы [ 6 ]

8 голосов
/ 06 мая 2009

Как вы можете видеть здесь, вызов notifyAll () для не ожидающего объекта не имеет никакого эффекта.

alt text

6 голосов
/ 06 мая 2009

Это совершенно нормально. Вы можете уведомить всех, кто ожидает, только на одном мониторе. Все остальные не заинтересованы. Объект, для которого вы вызываете notifyAll, - это просто монитор, который ожидают другие. Если никто не ждет, никто не должен быть уведомлен

2 голосов
/ 06 мая 2009

Совершенно нормальная ситуация.

Допустим, у вас есть очередь с потоком производителя, который помещает в нее элементы, и поток потребителя, удаляющий элементы из нее.

Теперь потребитель мог опустошить очередь и все еще быть занятым обработкой, поэтому никто не ждет, пока очередь не станет пустой. Теперь производитель добавляет новый элемент в очередь. Он должен вызвать notifyAll (), чтобы разбудить потребителя, если он ждет. Добавление дополнительной логики для проверки того, что кто-то ждет, и только вызов notifyAll () в этом случае добавит значительную (и очень склонную к сбоям) сложность в сценарий - гораздо проще просто вызывать notifyAll () каждый раз.

2 голосов
/ 06 мая 2009

Объект "ждет", а не ждет сам. Нить тот, кто ждет. Если никто не ждет, никто не проснется и ничего особенного не произойдет.

1 голос
/ 20 января 2012

Я мог бы только раскалывать волосы ;-) Возможно, было бы не совсем правильно думать о том, что потоки переводятся из состояния «ожидания» в состояние «работы» в 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();
        }
    }
}
1 голос
/ 06 мая 2009

Только ожидающие объекты получают уведомление. Object.wait () блокируется до истечения времени ожидания или уведомления - поэтому остается вопрос, как или почему вы думаете, что ожидающие объекты когда-либо будут получать уведомления? это не имеет смысла.

...