"Bună, Amigo!"

— Și încă câteva detalii. Să-i spunem sfaturi practice.

„Să presupunem că ai o metodă care așteaptă ceva și adoarme până când o condiție este îndeplinită.”

Dacă colecția este goală, atunci așteptăm
public synchronized Runnable getJob()
{
 if (jobs.size() == 0)
  this.wait();

 return jobs.remove(0);
}

„Documentația Java recomandă foarte insistent apelarea metodei wait într-o buclă:”

Dacă colecția este goală, atunci așteptăm
public synchronized Runnable getJob()
{
 while (jobs.size() == 0)
  this.wait();

 return jobs.remove(0);
}

"De ce? Chestia este că dacă firul se trezește, asta nu înseamnă că condiția este îndeplinită. Poate că au fost douăzeci de astfel de fire adormite. Toate s-au trezit, dar doar unul poate prelua sarcina."

„În linii mari, pot exista „alarme false”. Un dezvoltator bun trebuie să țină cont de acest lucru.”

— Înțeleg. Nu este mai ușor să folosești notificarea?

"Ei bine, ce se întâmplă dacă ar exista mai multe sarcini în listă? Notify este de obicei recomandat pentru utilizare de dragul optimizării. În toate celelalte cazuri, este recomandat să utilizați metoda notifyAll."

"BINE."

„Dar mai sunt. În primul rând, poate exista o situație în care cineva vă moștenește clasa, își adaugă propriile metode și, de asemenea, folosește wait/notifyAll. Cu alte cuvinte, poate exista o situație în care perechile independente wait/notifyAll așteaptă pe același obiect și nu știu unul despre celălalt. Deci ce ar trebui să faceți?"

„Apelați întotdeauna wait într-o buclă și verificați dacă condiția de terminare a buclei este adevărată!”

„Corect. Și pentru a fi destul de clar că nu poți scăpa de asta, mulți dezvoltatori subliniază că uneori firele se trezesc de la sine. Firele care sunt garantate că nu vor fi trezite accidental. Acesta pare să fie efectul secundar al optimizării codului într-un rulează mașină Java."

"Uau. Am înțeles. Fără o buclă, metoda așteptării nu este bună."