Почему метод wait() работает без notify()?

Заранее большое спасибо!

У меня были проблемы с синхронизацией двух потоков: основного и потока, который вызывается из StepRunner.java. Мне просто нужно, чтобы результат итерации отображался до начала следующей итерации.

Что я хочу:

Please enter step number [1, 2, 3 or 4] or 5 for exit: 2
Please enter natural value for factorial computing: 2
2! = 2
Please enter step number [1, 2, 3 or 4] or 5 for exit:

Чего я не хочу:

Please enter step number [1, 2, 3 or 4] or 5 for exit: 2
Please enter natural value for factorial computing: 2
Please enter step number [1, 2, 3 or 4] or 5 for exit: 2! = 2

Для этого я синхронизировал блок в StepRunner.java:

public void run() {
        thread.start();
        synchronized (thread) {
            try {
                while (thread.isAlive()) { /**Loop is an Oracle's recommendation*/
                    thread.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

Но почему метод wait() корректно работает без метода notify() в любом месте моего кода?


person Dmitry Bilko    schedule 28.03.2014    source источник
comment
Вы проверяли, что цикл вообще выполняется? Это всего лишь предположение, но, возможно, поток имеет свой собственный монитор (или, возможно, планировщик), и поэтому синхронизированный блок выполняется только после завершения потока и больше не существует.   -  person Thomas    schedule 28.03.2014
comment
Когда поток умирает, он уведомляет сам себя.   -  person Sotirios Delimanolis    schedule 28.03.2014


Ответы (1)


В Thread javadoc указано что Thread.notifyAll() вызывается внутри, когда поток завершается:

В этой реализации используется цикл вызовов this.wait, обусловленных this.isAlive. Когда поток завершается, вызывается метод this.notifyAll. Рекомендуется, чтобы приложения не использовали ожидание, уведомление или notifyAll в экземплярах Thread.

Как видите, использовать эту функцию не рекомендуется, ваш код можно переписать следующим образом:

thread.start();
try {
    thread.join();    
} catch (InterruptedException e) {
    e.printStackTrace();
}

Учитывая тот факт, что это утверждение появилось только в javadoc Java 7 и рекомендуется не использовать эту функциональность, похоже, что это поведение раньше было деталью реализации класса Thread, но люди стали полагаться на него, так что авторам языка пришлось документировать это.

person axtavt    schedule 28.03.2014