Sari la conținutul principal

Metodele wait, notify & notifyAll

Sa presupunem că avem 2 thread-uri: thread-ul 0 care calculează o valoare și o plasează în variabila a si thread-ul 1 care atunci când variabila a se actualizează, o afișează în interfața grafică a unui program. O posibilă implementare pentru funcția thread-ului 0, în pseudocod, ar fi:

function_thread_0:
noua_valoare = calculeaza_valoare_a()
mutex_a.lock()
a = noua_valoare
mutex_a.unlock()

O posibilă implementare pentru funcția thread-ului 1, în pseudocod, ar fi:

function_thread_1:
while(a nu s-a actualizat):
mutex_a.lock()
if (a s-a actualizat):
afiseaza(a)
a = -1 //Resetam valoarea lui a.
mutex_a.unlock()

Observăm o problemă cu această abordare: thread-ul 1 va cicla în bucla while de mai multe ori, chiar dacă thread-ul 0 nu-l actualizează pe a, ocupând inutil timp pe procesor. Această abordare poarta numele de busy waiting. Deși busy waiting nu este întotdeauna o idee rea, în cazul de față, presupunem că pentru a calcula noua valoarea a lui a, thread-ului 0 îi ia un timp îndelungat. Astfel, există o soluție mai bună oferită de primitevele Java wait(), notify() și notifyAll().

wait() - forțează thread-ul curent să intre în așteptare până când alt thread apelează notify() sau notifyAll() pe același obiect. Pentru ca aceasta să se întâmple, thread-ul curent trebuie să dețină monitorul obiectului respectiv. Deținerea monitorului se poate întâmpla în următoarele situații:

  • s-a executat o metodă synchronized pe obiectul respectiv
  • s-a executat un bloc synchronized pe obiectul respectiv
  • s-a executat o metodă synchronized statică pe clasa din care face parte obiectul respectiv
atenție

Evitați folosirea wait() asupra obiectelor cu vizibilitate globală (statice) sau asupra String-urilor cu valoare constanta (de ex: String myMonitorObject = "";), deoarece JVM optimizează intern accesul la astfel de variabile, având doar o singură instanță în cadrul programului.

notify() - alege aleatoriu un thread care așteaptă (a apelat wait()) monitorul obiectului respectiv și trece-l din starea de waiting în starea de running

notifyAll() - trece toate thread-urile care așteaptă (au apelat wait()) monitorul obiectului respectiv și trece-le din starea de waiting în starea de running

CheatSheet Wait-Notify