Beispiel dazu, dass Schlaf den Sperrvorgang nicht freigibt und Warten es tut
Hier gibt es zwei Klassen:
- Main : Enthält die Hauptmethode und zwei Threads.
-
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.
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?
3 Stimmen
Hier ist ein guter Artikel, der es beschreibt: qat.com/using-waitnotify-instead-thread-sleep-java
3 Stimmen
Es ist GANZ genau das Gegenteil - sleep "verwendet" alle verfügbaren CPU-Zyklen, aber da der Thread sich im "WARTEN" -Zustand befindet, können diese bei Bedarf abgegeben werden - tatsächlich geben die meisten Betriebssysteme automatisch die Zyklen ab WENN es möglich ist, daher wird Ihr Thread keine tatsächliche CPU-Last erzeugen... auf älteren Betriebssystemen wird er dies jedoch tun. Object.wait() hingegen verwendet NIE Zyklen (während er nicht benachrichtigt wird), da dies in vielen Fällen über Software-Unterbrechungen realisiert wird - private, flüchtige und transparente Sperren, implementiert durch die JVM. Thread.sleep ist schlechte Praxis.
0 Stimmen
@specializt "Thread.sleep ist eine schlechte Praxis", wenn es anstelle von wait verwendet wird. siehe stackoverflow.com/questions/17826651/… Aber guter Kommentar dabei.
0 Stimmen
Wenn Sie gerade auf diese Frage gestoßen sind, helfen Ihnen diese beiden Fragen, weitere Details zu erhalten, wenn Sie nach dem Lesen der Antwort verwirrt sind stackoverflow.com/questions/3362303/whats-a-monitor-in-java stackoverflow.com/questions/30262209/…