"Ciao, Amico!"

"E un altro paio di dettagli. Chiamiamolo consiglio pratico."

"Supponi di avere un metodo che aspetta qualcosa e si addormenta finché una condizione non è soddisfatta."

Se la raccolta è vuota, aspettiamo
public synchronized Runnable getJob()
{
 if (jobs.size() == 0)
  this.wait();

 return jobs.remove(0);
}

"La documentazione Java raccomanda molto insistentemente di chiamare il metodo wait in un ciclo:"

Se la raccolta è vuota, aspettiamo
public synchronized Runnable getJob()
{
 while (jobs.size() == 0)
  this.wait();

 return jobs.remove(0);
}

"Perché? Il fatto è che se il filo si sveglia, ciò non significa che la condizione sia soddisfatta. Forse c'erano venti di questi fili dormienti. Tutti si sono svegliati, ma solo uno può accettare il compito."

"In parole povere, possono esserci dei 'falsi allarmi'. Un buon sviluppatore deve tenerne conto."

"Capisco. Non è più facile usare solo la notifica?"

"Bene, e se ci fosse più di un'attività nell'elenco? Di solito si consiglia di utilizzare Notify per motivi di ottimizzazione. In tutti gli altri casi, si consiglia di utilizzare il metodo notifyAll."

"OK."

"Ma c'è di più. In primo luogo, potrebbe esserci una situazione in cui qualcuno eredita la tua classe, aggiunge i propri metodi e utilizza anche wait/notifyAll. In altre parole, potrebbe esserci una situazione in cui le coppie wait/notifyAll indipendenti attendono sullo stesso oggetto e non si conoscono l'un l'altro. Quindi cosa dovresti fare?"

"Chiama sempre wait in un loop e verifica che la condizione di terminazione del loop sia vera!"

"Giusto. E per chiarire che non puoi sfuggire a questo, molti sviluppatori sottolineano che a volte i thread si svegliano da soli. Thread che è garantito per non essere risvegliati accidentalmente. Questo sembra essere un effetto collaterale dell'ottimizzazione del codice in un eseguire una macchina Java."

"Whoa. Capito. Senza un ciclo, il metodo di attesa non va bene."