1350 Stimmen

Unterschied zwischen "wait()" vs "sleep()" in Java

Was ist der Unterschied zwischen einem wait() und sleep() in Threads?

Ist mein Verständnis richtig, dass ein wait()-ender Thread sich immer noch im Laufmodus befindet und CPU-Zyklen verwendet, während ein sleep()-ender Thread keine CPU-Zyklen verbraucht?

Warum haben wir beide wait() und sleep()?

Wie unterscheidet sich deren Implementierung auf niedrigerer Ebene?

61 Stimmen

Sehr gute Frage. Die Semantik beider ist leicht zu verwechseln.

1 Stimmen

Sehr gute Fragen, aber sie sind 2 in einem. Warum wir beide haben, ist nicht dasselbe wie wie sie auf einer niedrigeren Ebene implementiert werden können (und nicht sind!). Darauf habe ich auch geantwortet.

0 Stimmen

Angenommen ein Thread A befindet sich in einem synchronisierten Block, und während er in der CPU ist, wird dieser Thread einem anderen Thread B übergeben. In welchem Zustand wird Thread A jetzt sein? Werden die anderen Threads, die auf diesem synchronisierten Block warten, jetzt eintreten?

3voto

shikjohari Punkte 2170

wait gibt das Schloss frei und sleep nicht. Ein Thread im Wartezustand ist berechtigt, aufzuwachen, sobald notify oder notifyAll aufgerufen wird. Aber im Fall von sleep behält der Thread das Schloss und wird erst berechtigt, sobald die Schlafzeit abgelaufen ist.

0 Stimmen

Wenn der Thread also für 10 Sekunden schläft und eine unterbrochene Ausnahme auftritt ????

0 Stimmen

@Geek Ein InterruptedException wird geworfen, genau wie es in der Javadoc steht.

0 Stimmen

@EJP: Bist du derselbe EJP, der in den sun.java.com Foren war? Zumindest deutet dein Score darauf hin :-)

3voto

Justin Punkte 82143

Sie haben Recht - Sleep() bewirkt, dass der Thread "schläft" und die CPU wird andere Threads verarbeiten (auch bekannt als Kontextwechsel), während ich glaube, dass Wait die CPU dazu bringt, den aktuellen Thread zu verarbeiten.

Wir haben beide, weil obwohl es sinnvoll erscheinen mag, anderen Leuten die CPU nutzen zu lassen, während Sie sie nicht verwenden, gibt es tatsächlich einen Overhead für den Kontextwechsel - je nachdem, wie lange der Schlaf ist, kann es teurer in CPU-Zyklen sein, Threads zu wechseln, als einfach Ihren Thread für ein paar ms nichts tun zu lassen.

Beachten Sie auch, dass Sleep einen Kontextwechsel erzwingt.

Außerdem - im Allgemeinen ist es nicht möglich, den Kontextwechsel zu steuern - während des Wartens kann das Betriebssystem (und wird es bei längeren Wartezeiten) wählen, andere Threads zu verarbeiten.

7 Stimmen

Wait() hält die CPU nicht beim Verarbeiten des aktuellen Threads. Es ist ähnlich wie sleep, da es auch einen Kontextwechsel verursacht: javamex.com/tutorials/threads/context_switch.shtml. Ich habe seit einem halben Jahr überall auf Stackoverflow danach gefragt und es scheint, als wüsste niemand, was der Unterschied zwischen wait/notify und sleep/interrupt ist.

0 Stimmen

Obwohl sleep die CPU nicht im Verarbeitungsprozess des aktuellen Threads hält, glaube ich, dass es trotzdem ein kleines bisschen eine Belastung für die CPU ist, weil die CPU den Zeitpunkt verfolgen muss, wann der Schlaf enden soll. Sie hat nicht diesen externen Auslöser wie "notify" in wait. Nicht wahr?

0 Stimmen

@ VladimirNabokov, Der externe Trigger ist interrupt. Die Endzeit ist n in wait(n). ¶¶ Es sind jetzt 8 Jahre vergangen und immer noch hat niemand die Antwort!

2voto

User10001 Punkte 1275

Die sleep()-Methode führt dazu, dass der aktuelle Thread vom Laufzustand in den Blockzustand für eine bestimmte Zeit wechselt. Wenn der aktuelle Thread das Schloss eines Objekts besitzt, behält er es bei, was bedeutet, dass andere Threads keine synchronisierte Methode in diesem Klassenobjekt ausführen können.

Die wait()-Methode führt dazu, dass der aktuelle Thread entweder für eine bestimmte Zeit oder bis zu einem Benachrichtigung in den Blockzustand wechselt, aber in diesem Fall gibt der Thread das Schloss des Objekts frei (was bedeutet, dass andere Threads alle synchronisierten Methoden des aufrufenden Objekts ausführen können).

2voto

negora Punkte 151

Nach meiner Meinung liegt der Hauptunterschied zwischen beiden Mechanismen darin, dass Schlaf/Unterbrechung die grundlegendste Art ist, Threads zu bearbeiten, während Warten/Benachrichtigen eine Abstraktion ist, die darauf abzielt, die Thread-Interkommunikation zu erleichtern. Das bedeutet, dass Schlaf/Unterbrechung alles können kann, aber dass diese spezifische Aufgabe schwieriger zu erledigen ist.

Warum ist Warten/Benachrichtigen besser geeignet? Hier sind einige persönliche Überlegungen:

  1. Es erzwingt Zentralisierung. Es ermöglicht die Koordination der Kommunikation zwischen einer Gruppe von Threads mit einem einzigen gemeinsamen Objekt. Dies vereinfacht die Arbeit erheblich.

  2. Es erzwingt Synchronisation. Denn es zwingt den Programmierer, den Aufruf von Warten/Benachrichtigen in einem synchronisierten Block zu wrap.

  3. Es ist unabhängig vom Thread-Ursprung und der Anzahl. Mit diesem Ansatz können Sie beliebig viele Threads hinzufügen, ohne die anderen Threads zu bearbeiten oder eine Liste der vorhandenen zu führen. Wenn Sie Schlaf/Unterbrechung verwendet haben, müssten Sie zunächst die Referenzen auf die schlafenden Threads speichern und sie dann manuell einzeln unterbrechen.

Ein Beispiel aus dem wirklichen Leben, das gut erklärt, ist ein klassisches Restaurant und die Methode, die das Personal verwendet, um untereinander zu kommunizieren: Die Kellner hinterlassen die Kundenwünsche an einem zentralen Ort (einer Pinnwand, einem Tisch usw.), läuten eine Glocke und die Arbeiter aus der Küche kommen, um diese Wünsche abzuholen. Sobald ein Gericht fertig ist, läuten die Küchenmitarbeiter erneut die Glocke, damit die Kellner Bescheid wissen und es zu den Kunden bringen.

2voto

Dhiral Pandya Punkte 9709

Beispiel dazu, dass Schlaf den Sperrvorgang nicht freigibt und Warten es tut

Hier gibt es zwei Klassen:

  1. Main : Enthält die Hauptmethode und zwei Threads.
  2. Singleton : Dies ist eine Singleton-Klasse mit zwei statischen Methoden getInstance() und getInstance(boolean isWait).

    public class Main {
    
    private static Singleton singletonA = null;
    private static Singleton singletonB = null;
    
    public static void main(String[] args) throws InterruptedException {
    
    Thread threadA = new Thread() {
        @Override
        public void run() {
    
            singletonA = Singleton.getInstance(true);
    
        }
    };
    
    Thread threadB = new Thread() {
        @Override
        public void run() {
            singletonB = Singleton.getInstance();
    
            while (singletonA == null) {
                System.out.println("SingletonA noch null");
            }
    
            if (singletonA == singletonB) {
                System.out.println("Beide Singleton sind gleich");
            } else {
                System.out.println("Beide Singleton sind nicht gleich");
            }
    
        }
    };
    
    threadA.start();
    threadB.start();
    
     }
    }

und

public class Singleton {

    private static Singleton _instance;

    public static Singleton getInstance() {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null)
                _instance = new Singleton();
        }
    }
    return _instance;

}

public static Singleton getInstance(boolean isWait) {

    if (_instance == null) {
        synchronized (Singleton.class) {
            if (_instance == null) {
                if (isWait) {
                    try {
                        // Singleton.class.wait(500);//Mit warten
                        Thread.sleep(500);// Mit Sleep
                        System.out.println("_instance :"
                                + String.valueOf(_instance));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                _instance = new Singleton();
            }
        }
    }
    return _instance;

 }
}

Führen Sie nun dieses Beispiel aus, Sie werden folgende Ausgabe erhalten:

_instance :null
Beide Singleton sind gleich

Hier sind Singleton-Instanzen, die von threadA und threadB erstellt wurden, gleich. Das bedeutet, threadB wartet draußen, bis threadA seinen Sperrvorgang freigibt.

Ändern Sie nun die Singleton.java, indem Sie die Methode Thread.sleep(500); kommentieren und Singleton.class.wait(500); auskommentieren. Hier wird aufgrund der Methode Singleton.class.wait(500); threadA alle erworbenen Sperren freigeben und in den Zustand "Nicht ausführbar" wechseln, threadB wird die Möglichkeit haben, in den synchronisierten Block einzutreten.

Führen Sie es erneut aus:

SingletonA noch null
SingletonA noch null
SingletonA noch null
_instance :com.omt.sleepwait.Singleton@10c042ab
SingletonA noch null
SingletonA noch null
SingletonA noch null
Beide Singleton sind nicht gleich

Hier sind die Singleton-Instanzen, die von threadA und threadB erstellt wurden, NICHT gleich, weil threadB die Möglichkeit hatte, in den synchronisierten Block zu gelangen und nach 500 Millisekunden threadA von seiner letzten Position aus gestartet wurde und ein weiteres Singleton-Objekt erstellt hat.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X