Java-Thread wartet, notify und notifyAll Beispiel

Die Object-Klasse in Java enthält drei finale Methoden, die es Threads ermöglichen, Informationen über den Sperrstatus einer Ressource auszutauschen. Diese Methoden sind wait(), notify() und notifyAll(). Heute werden wir uns mit wait, notify und notifyAll in einem Java-Programm befassen.

Warten, Benachrichtigen und Benachrichtigen aller in Java

Der aktuelle Thread, der diese Methoden für ein Objekt aufruft, sollte das Objekt überwachen, sonst wird eine Ausnahme von Typ java.lang.IllegalMonitorStateException ausgelöst.

Warten

Die Warten-Methoden des Objekts haben drei Varianten. Eine wartet unbegrenzt darauf, dass ein anderer Thread die notify- oder notifyAll-Methode für das Objekt aufruft, um den aktuellen Thread aufzuwecken. Die anderen beiden Varianten setzen den aktuellen Thread für eine bestimmte Zeit in den Wartezustand, bevor sie aufwachen.

Benachrichtigen

notify-Methode weckt nur einen auf das Objekt wartenden Thread auf, und dieser Thread beginnt seine Ausführung. Wenn also mehrere Threads auf ein Objekt warten, weckt diese Methode nur einen von ihnen auf. Die Wahl des Threads, der aufgeweckt wird, hängt von der Implementierung des Thread-Managements des Betriebssystems ab.

notifyAll

Die notifyAll-Methode weckt alle Threads auf, die auf das Objekt warten, obwohl davon abhängt, welcher zuerst verarbeitet wird, von der Betriebssystemimplementierung. Diese Methoden können verwendet werden, um das Producer-Consumer-Problem zu implementieren, bei dem Consumer-Threads auf Objekte in der Warteschlange warten und Producer-Threads Objekte in die Warteschlange legen und die wartenden Threads benachrichtigen. Schauen wir uns ein Beispiel an, bei dem mehrere Threads an demselben Objekt arbeiten und wir die wait-, notify- und notifyAll-Methoden verwenden.

Nachricht

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;
    }

}

Bedienungsperson

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());
            //Verarbeite die Nachricht jetzt
            System.out.println(name+" processed: "+msg.getMsg());
        }
    }

}

Mitteilender

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 mehrere Threads von Waiter und Notifier erstellt und startet.

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");
    }

}

Wenn wir das obige Programm aufrufen, sehen wir die folgende Ausgabe, aber das Programm wird nicht abgeschlossen, weil zwei Threads auf das Message-Objekt warten und die notify()-Methode nur einen von ihnen aufweckt, der andere Thread wartet immer noch darauf, benachrichtigt zu werden.

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

Wenn wir den notify()-Aufruf kommentieren und den notifyAll()-Aufruf in der Notifier-Klasse aktivieren, wird die folgende Ausgabe erzeugt.

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

Da die notifyAll()-Methode beide Waiter-Threads aufweckt, wird das Programm nach der Ausführung abgeschlossen und beendet. Das ist alles für wait, notify und notifyAll in Java.

Source:
https://www.digitalocean.com/community/tutorials/java-thread-wait-notify-and-notifyall-example