Как долго после выполнения wait () поток ожидает, если он не получает уведомления от других потоков?
В приведенном ниже примере, поскольку основной поток не получает уведомления от дочернего потока, он должен ждать вечно. Но основной поток выполняется, и результат следующего примера:
c
l
total: 19900
Почему выполняется основной поток?
public class ThreadX extends Thread {
static int total = 0;
public void run() {
synchronized (this) {
for (int i = 0; i < 200; i++) {
total = total + i;
}
System.out.println("c");
}
}
public static void main(String[] args) throws InterruptedException {
ThreadX t = new ThreadX();
t.start();
synchronized (t) {
t.wait();
System.out.println("l");
}
System.out.println("total: " + total);
}
}
Ответы
Ответ на основной вопрос
Проверить Thread#join(long):
[...] Когда поток завершается
this.notifyAll
, вызывается метод. [...]
Обратите внимание, что Thread#join()
эта функция вызывается с помощью 0
, что означает навсегда.
[...] Таймаут 0 означает ждать вечно.
Итак, в вашем случае здесь t
просто вызывается, notifyAll
когда он завершается, что уведомляет основной поток, который ожидает t
.
Это неинтуитивное поведение является причиной того, что в документации написано следующее:
Рекомендуется , чтобы приложения не используют
wait
,notify
илиnotifyAll
наThread
случаях.
Ответ на вопрос-заголовок
Выписка Object#wait(или JLS (17.2.1. Подождите) ):
Поток может проснуться без уведомления, прерывания или тайм-аута, так называемое ложное пробуждение. Хотя на практике это случается редко, приложения должны защищаться от этого, проверяя условие, которое должно было вызвать пробуждение потока, и продолжая ждать, если условие не выполняется.
Таким образом, потоки в Java могут проснуться в любой момент. Ложное пробуждение маловероятно, но может произойти.