Después de ejecutar wait (), ¿cuánto tiempo espera un hilo si no recibe una notificación de otros hilos?
En el siguiente ejemplo, como el hilo principal no recibe notificaciones del hilo secundario, debería esperar eternamente. Pero el hilo principal se está ejecutando y el resultado del siguiente ejemplo es:
c
l
total: 19900
¿Por qué se ejecuta el subproceso principal?
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);
}
}
Respuestas
Respuesta al cuerpo de preguntas
Mira Thread#join(long):
[...] Cuando un hilo termina
this.notifyAll
, se invoca el método. [...]
Observe que Thread#join()
llama a esa función con 0
, lo que significa para siempre.
[...] Un tiempo de espera de 0 significa esperar eternamente.
Entonces, en su caso, aquí t
solo llama notifyAll
cuando termina, lo que notifica al hilo principal que está esperando t
.
Este comportamiento poco intuitivo es la razón por la que escriben lo siguiente en la documentación:
Se recomienda que las aplicaciones no utilizan
wait
,notify
onotifyAll
enThread
casos.
Respuesta al título de la pregunta
Verifique Object#wait(o JLS (17.2.1. Espere) ):
Un hilo puede despertarse sin que se le notifique, se interrumpa o se agote el tiempo, lo que se denomina un despertar espurio. Si bien esto rara vez ocurrirá en la práctica, las aplicaciones deben protegerse contra esto probando la condición que debería haber provocado la activación del hilo y continuar esperando si la condición no se cumple.
Por lo tanto, los subprocesos en Java pueden activarse en cualquier momento. No es muy probable que se produzca un despertar falso, pero puede suceder.