Singleton-Muster: ist ein häufig verwendetes Software-Designmuster. In seiner Kernstruktur enthält es eine spezielle Klasse namens Singleton. Eine Klasse hat nur eine Instanz, das heißt, eine Klasse hat nur eine Objektinstanz.
Für einige Klassen im System ist nur eine Instanz wichtig. Beispielsweise kann es in einem System mehrere Druckaufgaben geben, aber beim Verkauf von Tickets kann es insgesamt 100 geben Für ein Ticket können mehrere Fenster gleichzeitig Tickets verkaufen, es muss jedoch sichergestellt werden, dass es nicht zu einer Überbuchung kommt (die verbleibende Anzahl an Tickets ist hier eine einzelne Instanz, und der Ticketverkauf erfordert Multithreading). Wenn kein Mechanismus zur Eindeutigkeit des Fensterobjekts verwendet wird, werden mehrere Fenster angezeigt. Wenn diese Fenster alle denselben Inhalt anzeigen, werden durch wiederholtes Erstellen Ressourcen verschwendet.
Anwendungsszenario (Quelle: „Dahua Design Pattern“):
Anforderung: Erstellen Sie ein Toolbox-Fenster im Frontend. Die Toolbox wird entweder nicht oder nur eines angezeigt wird angezeigt.
Es ist ein Problem aufgetreten: Das Fenster „Toolbox“ wird jedes Mal wiederholt erstellt, wenn Sie auf das Menü klicken.
Lösung 1: Verwenden Sie die if-Anweisung, um bei jedem Erstellen eines Objekts zunächst festzustellen, ob es null ist. Wenn es null ist, erstellen Sie das Objekt erneut.
Anforderungen: Wenn Sie das Toolbox-Formular an 5 Stellen instanziieren müssen
Aufgetretene Probleme: Dieser kleine Fehler muss an 5 Stellen geändert werden, und der Code wird wiederholt und die Codeauslastungsrate erhöht ist niedrig
Lösung 2: Verwenden Sie das Singleton-Muster, um sicherzustellen, dass eine Klasse nur eine Instanz hat, und stellen Sie einen globalen Zugriffspunkt für den Zugriff darauf bereit.
Der Singleton-Modus kann in Lazy-Stil und Hungrig-Stil unterteilt werden :
Lazy-Singleton-Modus: Wird nicht initialisiert, wenn die Klasse geladen wird.
Singleton-Modus im Hungry-Stil: Die Initialisierung ist abgeschlossen, wenn die Klasse geladen ist. Daher ist das Laden der Klasse langsam, die Geschwindigkeit der Objekterfassung jedoch hoch.
Der erste Typ (fauler Typ, Thread unsicher):
public class SingletonDemo1 {private static SingletonDemo1 instance;private SingletonDemo1(){}public static SingletonDemo1 getInstance(){if (instance == null) { instance = new SingletonDemo1(); }return instance; } }
Diese Art zu schreiben ist sehr Lazy Loading Offensichtlich, aber fatalerweise, funktioniert es mit mehreren Threads nicht richtig.
Der zweite Typ (fauler Typ, Thread-sicher):
public class SingletonDemo2 {private static SingletonDemo2 instance;private SingletonDemo2(){}public static synchronized SingletonDemo2 getInstance(){if (instance == null) { instance = new SingletonDemo2(); }return instance; } }
Diese Schreibweise ist im getInstance() Der Methode wird eine synchronisierte Sperre hinzugefügt. Es funktioniert gut in mehreren Threads und scheint ein gutes verzögertes Laden zu haben, ist jedoch sehr ineffizient (aufgrund von Sperren) und erfordert in den meisten Fällen keine Synchronisierung.
Der dritte Typ (hungriger Mann):
public class SingletonDemo3 {private static SingletonDemo3 instance = new SingletonDemo3();private SingletonDemo3(){}public static SingletonDemo3 getInstance(){return instance; } }
Diese Methode vermeidet viele Probleme basierend auf dem Klassenloder Beim Thread-Synchronisationsmechanismus wird die Instanz jedoch instanziiert. Zu diesem Zeitpunkt wird durch die Initialisierung der Instanz offensichtlich nicht der Effekt des verzögerten Ladens erzielt.
Der vierte Typ (HungrigHan, Variante):
public class SingletonDemo4 {private static SingletonDemo4 instance = null;static{ instance = new SingletonDemo4(); }private SingletonDemo4(){}public static SingletonDemo4 getInstance(){return instance; } }
Oberfläche Es scheint ganz anders zu sein, aber tatsächlich ist der dritte Weg fast derselbe, beide werden in der Klasseninitialisierungsinstanz instanziiert
Der fünfte Weg (statische interne Klasse):
public class SingletonDemo5 {private static class SingletonHolder{private static final SingletonDemo5 instance = new SingletonDemo5(); }private SingletonDemo5(){}public static final SingletonDemo5 getInsatance(){return SingletonHolder.instance; } }
Diese Methode verwendet auch den Classloder-Mechanismus, um sicherzustellen, dass es beim Initialisieren der Instanz nur einen Thread gibt. Es ähnelt dem dritten Der Unterschied zwischen der vierten und der vierten Methode besteht darin (sehr subtiler Unterschied): Die dritte und vierte Methode bestehen darin, dass die Instanz instanziiert wird, solange die Singleton-Klasse geladen ist (der Lazy-Loading-Effekt wird nicht erreicht). Die Singleton-Klasse ist geladen. Ja, die Instanz ist nicht unbedingt initialisiert. Da die SingletonHolder-Klasse nicht aktiv verwendet wird, wird die SingletonHolder-Klasse nur explizit geladen, indem die getInstance-Methode aufgerufen wird, um die Instanz zu instanziieren. Stellen Sie sich vor, das Instanziieren einer Instanz verbraucht Ressourcen und ich möchte, dass sie träge geladen wird. Andererseits möchte ich sie nicht instanziieren, wenn die Singleton-Klasse geladen wird, da ich nicht sicherstellen kann, dass die Singleton-Klasse in anderen Fällen aktiv verwendet werden kann Orte geladen ist, ist es zu diesem Zeitpunkt offensichtlich unangemessen, eine Instanz zu instanziieren. Derzeit erscheint diese Methode sinnvoller als die dritte und vierte Methode.
Sechste (Aufzählung):
public enum SingletonDemo6 { instance;public void whateverMethod(){ } }
Diese Methode wird von Josh Bloch, Autor von Effective Java The, befürwortet Die Methode kann nicht nur Multithread-Synchronisationsprobleme vermeiden, sondern auch verhindern, dass durch Deserialisierung neue Objekte erstellt werden. Ich persönlich denke jedoch, dass die Verwendung der Enum-Funktion erst in 1.5 hinzugefügt wurde Mit dieser Methode fühlt man sich beim Schreiben unweigerlich fremd. In der Praxis sehe ich selten jemanden, der so schreibt.
Siebter Typ (Doppelprüfschloss):
public class SingletonDemo7 {private volatile static SingletonDemo7 singletonDemo7;private SingletonDemo7(){}public static SingletonDemo7 getSingletonDemo7(){if (singletonDemo7 == null) {synchronized (SingletonDemo7.class) {if (singletonDemo7 == null) { singletonDemo7 = new SingletonDemo7(); } } }return singletonDemo7; } }
Dies ist eine aktualisierte Version der zweiten Methode, die allgemein als Doppelprüfsperre bezeichnet wird. Eine ausführliche Einführung finden Sie unter:
Nach JDK1.5 kann die Doppelprüfsperre den Singleton-Effekt normal erzielen.
Einzelne Instanz im Multithreading Wenn in einem Multithread-Programm mehrere Threads gleichzeitig auf die einzelne Instanz zugreifen, ist es möglich, mehrere zu erstellen Instanzen. Zu diesem Zeitpunkt müssen Sie es mit einem „Schloss“ sperren. Einschließlich Sperren, Deadlocks und Kommunikation zwischen Sperren. Dieser Teil über Multithreading wird später ausführlich erläutert!
Referenz:
Das obige ist der detaillierte Inhalt vonTeilen im Singleton-Modus. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!