Das Singleton-Muster ist eines der 23 Entwurfsmuster. Sein Zweck besteht darin, dasselbe Objekt zurückzugeben, unabhängig davon, wie oft es aufgerufen wird.
Es ist in zwei Strukturen unterteilt: Der Lazy-Man-Stil und der Hungrig-Man-Stil. Beginnen wir mit dem Hungrig-Man-Stil.
öffentliche Klasse Single { private static Single single = new Single(); private Single() { } public Single getInstance() { return single;
Aus dem obigen Programm ist ersichtlich, dass unser Ziel, dasselbe Objekt zu laden, tatsächlich erreicht wurde. Wenn diese Klasse über mehrere solcher Methoden verfügt, verwenden wir diese möglicherweise nicht in diesem Objekt führt zu einer Speicherverschwendung. So entstand das Lazy-Singleton-Muster. Der Code lautet wie folgt:
public class Single { private static Single single = null; private Single() { } public Single getInstance() { if(single==null){ single = new Single( } }
Auf diese Weise ist das Objekt nur dann neu, wenn wir es tatsächlich aufrufen, aber dabei gibt es ein Problem.
Wenn der zweite Teil des obigen Codes beim ersten Laden von zwei Threads aufgerufen wird, werden zwei verschiedene Objekte generiert, sodass er nicht sicher für Threads ist. Zu diesem Zeitpunkt denken Sie darüber nach, eine Sperre hinzuzufügen, den Code nach dem Sperren ist wie folgt:
public class Single { private static Single single = null; private Single() { } public synchronisiert Single getInstance() { if (single == null) { single = new Single( } }
Dadurch wird zwar Thread-Sicherheit erreicht, aber wenn die Sperrmethode viele Aufgaben ausführen muss, dauert der Aufruf dieser Methode lange, was für den Server fatal ist, denn wenn ein Thread diese Methode weiterhin aufruft, gibt es keine Möglichkeit zur Anpassung Andere Threads und der Server werden blockiert. Dann lautet der aktualisierte Code wie folgt:
public class Single { priate static Single single = null; private Single() { } public Single getInstance() { if (single == null) { synchronisiert (Single.class) { single = new Single(); } }
Nach sorgfältiger Beobachtung habe ich festgestellt, dass es auf diese Weise keine Sperre gibt. Wenn zwei Threads zum ersten Mal bei der Methode getInstance() ankommen, muss einer von ihnen blockiert werden, nachdem der andere die Ausführung abgeschlossen hat Um festzustellen, ob es leer ist, wird weiterhin ein Objekt erstellt. Auf diese Weise werden mehrere Objekte generiert und dann aktualisiert. Der resultierende Code lautet wie folgt:
öffentliche Klasse Single { private static Single single = null; private Single() { } public Single getInstance() { if (single == null) { synchronisiert (Single.class) { if (single == null) { single = new Single (); } } return single;
Auf diese Weise tritt das obige Problem nicht auf und es wird nur einmal gesperrt, da bei der zweiten Ausführung der Methode die if-Beurteilung übersprungen wird und die einzelne Methode nicht erneut gesperrt wird , und die Ausführungseffizienz wird sehr hoch sein.
Trotzdem gibt es immer noch ein Problem, da wir nicht sicher sein können, ob dem Objekt zuerst ein Wert im Speicher zugewiesen wird oder ob das Objekt zuerst erstellt wird, sodass das zweite Programm nach 5 möglicherweise ein halbinitialisiertes Objekt erhält , können wir das Schlüsselwort volatile verwenden, um diese Situation zu vermeiden. Der Code lautet wie folgt:
öffentliche Klasse Single { private static volatile Single single = null; private Single() { } public Single getInstance() { if (single == null) { synchronisiert (Single.class) { if (single == null) { single = new Single(); } } return single;
Aber diese Situation wird selten genutzt, ich bin nur hier, um zu lernen, hehe