Dopo aver eseguito wait (), quanto tempo attende un thread se non riceve una notifica da altri thread?
Nell'esempio seguente, poiché il thread principale non riceve una notifica dal thread figlio, dovrebbe attendere per sempre. Ma il thread principale viene eseguito e l'output dell'esempio seguente è:
c
l
total: 19900
Perché il thread principale viene eseguito?
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);
}
}
Risposte
Rispondi al corpo della domanda
Check out Thread#join(long):
[...] Quando un thread termina, il
this.notifyAll
metodo viene invocato. [...]
Si noti che Thread#join()
chiama quella funzione con 0
, che significa per sempre.
[...] Un timeout di 0 significa aspettare per sempre.
Quindi nel tuo caso qui t
chiama solo notifyAll
quando termina, il che notifica il thread principale che è in attesa t
.
Questo comportamento non intuitivo è il motivo per cui scrivono quanto segue nella documentazione:
Si raccomanda di non utilizzare le applicazioni
wait
,notify
onotifyAll
suThread
istanze.
Rispondi al titolo della domanda
Check out Object#wait(o JLS (17.2.1. Wait) ):
Un thread può attivarsi senza essere avvisato, interrotto o scaduto, un cosiddetto risveglio spurio. Sebbene ciò si verifichi raramente nella pratica, le applicazioni devono proteggersi da esso verificando la condizione che avrebbe dovuto causare il risveglio del thread e continuando ad attendere se la condizione non è soddisfatta.
Quindi i thread in Java possono attivarsi in qualsiasi momento. Un risveglio spurio non è molto probabile ma può accadere.