De Object-klasse in Java bevat drie finale methoden die threads in staat stellen te communiceren over de vergrendelingsstatus van een resource. Deze methoden zijn wait(), notify() en notifyAll(). Dus vandaag zullen we kijken naar wait, notify en notifyAll in een Java-programma.
wait, notify en notifyAll in Java
De huidige thread die deze methoden aanroept op een object, moet het object monitor hebben, anders wordt een uitzondering van het type java.lang.IllegalMonitorStateException gegenereerd.
wait
De Object wait-methoden hebben drie varianten. De eerste wacht oneindig op een andere thread die de notify- of notifyAll-methode aanroept op het object om de huidige thread wakker te maken. De andere twee varianten laten de huidige thread voor een specifieke periode wachten voordat ze worden gewekt.
notify
notify-methode wekt slechts één wachtende thread op het object en die thread begint met uitvoeren. Dus als er meerdere threads wachten op een object, zal deze methode er slechts één van wakker maken. De keuze van de thread om wakker te worden, hangt af van de implementatie van het threadbeheer van het besturingssysteem.
notifyAll
notifyAll-methode wekt alle threads op die wachten op het object, hoewel welke eerst wordt verwerkt afhangt van de OS-implementatie. Deze methoden kunnen worden gebruikt om het producent-consumentprobleem te implementeren, waarbij consumerende threads wachten op objecten in de wachtrij en producentthreads objecten in de wachtrij plaatsen en de wachtende threads op de hoogte stellen. Laten we een voorbeeld bekijken waarbij meerdere threads werken aan hetzelfde object en we wait-, notify- en notifyAll-methoden gebruiken.
Bericht
A java bean class on which threads will work and call wait and notify methods.
package com.journaldev.concurrency;
public class Message {
private String msg;
public Message(String str){
this.msg=str;
}
public String getMsg() {
return msg;
}
public void setMsg(String str) {
this.msg=str;
}
}
Bediende
A class that will wait for other threads to invoke notify methods to complete it’s processing. Notice that Waiter thread is owning monitor on Message object using synchronized block.
package com.journaldev.concurrency;
public class Waiter implements Runnable{
private Message msg;
public Waiter(Message m){
this.msg=m;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
synchronized (msg) {
try{
System.out.println(name+" waiting to get notified at time:"+System.currentTimeMillis());
msg.wait();
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(name+" waiter thread got notified at time:"+System.currentTimeMillis());
//verwerk het bericht nu
System.out.println(name+" processed: "+msg.getMsg());
}
}
}
Melder
A class that will process on Message object and then invoke notify method to wake up threads waiting for Message object. Notice that synchronized block is used to own the monitor of Message object.
package com.journaldev.concurrency;
public class Notifier implements Runnable {
private Message msg;
public Notifier(Message msg) {
this.msg = msg;
}
@Override
public void run() {
String name = Thread.currentThread().getName();
System.out.println(name+" started");
try {
Thread.sleep(1000);
synchronized (msg) {
msg.setMsg(name+" Notifier work done");
msg.notify();
// msg.notifyAll();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
WaitNotifyTest
Testklasse die meerdere threads van Waiter en Melder zal maken en ze zal starten.
package com.journaldev.concurrency;
public class WaitNotifyTest {
public static void main(String[] args) {
Message msg = new Message("process it");
Waiter waiter = new Waiter(msg);
new Thread(waiter,"waiter").start();
Waiter waiter1 = new Waiter(msg);
new Thread(waiter1, "waiter1").start();
Notifier notifier = new Notifier(msg);
new Thread(notifier, "notifier").start();
System.out.println("All the threads are started");
}
}
Wanneer we het bovenstaande programma aanroepen, zien we de onderstaande uitvoer, maar het programma zal niet volledig worden uitgevoerd omdat er twee threads wachten op het Message-object en de notify() methode slechts één ervan heeft gewekt, de andere thread wacht nog steeds om op de hoogte te worden gesteld.
waiter waiting to get notified at time:1356318734009
waiter1 waiting to get notified at time:1356318734010
All the threads are started
notifier started
waiter waiter thread got notified at time:1356318735011
waiter processed: notifier Notifier work done
Als we de notify() oproep uitcommentariëren en de notifyAll() oproep in de Melderklasse uitcommentariëren, zal dit de geproduceerde uitvoer zijn.
waiter waiting to get notified at time:1356318917118
waiter1 waiting to get notified at time:1356318917118
All the threads are started
notifier started
waiter1 waiter thread got notified at time:1356318918120
waiter1 processed: notifier Notifier work done
waiter waiter thread got notified at time:1356318918120
waiter processed: notifier Notifier work done
Aangezien de notifyAll() methode beide Waiter-threads wakker maakt, voltooit het programma en eindigt het na uitvoering. Dat is alles voor wait, notify en notifyAll in Java.
Source:
https://www.digitalocean.com/community/tutorials/java-thread-wait-notify-and-notifyall-example