Das Singleton-Muster ist am einfachsten zu verstehen und der einfachste Weg, um den Code im Entwurfsmuster von Hand geschrieben zu haben, aber es sind nicht viele Wissenspunkte beteiligt, so dass es häufig als Interviewfrage verwendet wird. Im Allgemeinen werden Singletons auf fünf Arten geschrieben: faul, hungrig, Double Check -Sperre, statische interne Klassen und Aufzählung. Um den Lernprozess aufzuzeichnen, wurden hier mehrere gängige Methoden zum Schreiben von Singleton -Schreibmethoden erstellt.
Bronze 5: (faul beladen, aber Thread ist nicht sicher)
Auf die Frage nach der Implementierung eines Singleton -Musters besteht die erste Reaktion vieler Menschen darin, den folgenden Code zu schreiben, einschließlich der gleichen Lehren in Lehrbüchern.
öffentliche Klasse Singleton {private statische Singleton -Instanz; private Singleton () {} public static Singleton getInstance () {if (instance == null) {instance = new Singleton (); } return Instance; }}Dieser Code ist einfach und unkompliziert und verwendet einen verzögerten Lademodus, aber Threads sind nicht sicher. Das Aufrufen der Methode getInstance () in einer Umgebung mit mehreren Threads kann dazu führen, dass mehrere Threads den Programmcode-Block von iF-Anweisung eingeben.
Fauler Stil: Synchronisiert (faul beladen, fadensicher, aber nicht effizient)
Um das obige Problem zu lösen, besteht der einfachste Weg, die gesamte GetInstance () -Methode auf die Synchronisierung festzulegen.
öffentliche Klasse Singleton {private statische Singleton -Instanz; private Singleton () {} public static synchronisierte Singleton getInstance () {if (instance == null) {instance = new Singleton (); } return Instance; }}Obwohl es mit Gewinde und verzögerter Belastung ist, ist es nicht effizient. Denn jederzeit kann es nur einen Thread geben, der die Methode getInstance () aufruft. Der synchronisierte Betrieb muss jedoch nur beim ersten Anruf benötigt werden, dh wenn das Singleton -Instanzobjekt erstmals erstellt wird. Dieses Muster bewirkt, dass nur ein Thread auch nach dem Erstellen des Singleton auf die Methode getInstance () zugreift, was zu potenziellen Leistungsproblemen führen kann. Dies führt zu einem Doppelprüfschloss.
Hungriger Stil: Statisches Endfeld (nicht faul beladen)
Diese Methode ist sehr einfach, da die Instanz eines Singletons als statisch endgültig deklariert und initialisiert wird, wenn die Klasse zum ersten Mal in den Speicher geladen wird. Das Erstellen eines Instanzobjekts ist also mit Thread-Safe (garantiert durch die JVM-Implementierung).
öffentliche Klasse Singleton {// Initialisieren Sie private statische Final -Singleton Instance = new Singleton (); private singleton () {} public static singleton getInstance () {// Singleton mit statischer Fabrikrückgabeinstanz; }}Es ist kein fauler Lademodus, die Instanz wird von Anfang an initialisiert, nachdem die Klasse geladen wurde, selbst wenn der Client die Methode getInstance () nicht aufruft. Dies führt zu einigen Verwendungsbeschränkungen: Beispielsweise hängt die Erstellung einer Singleton -Instanz von Parametern oder Konfigurationsdateien ab. Bevor getInstance () eine bestimmte Methode aufgerufen werden muss, um Parameter darauf zu setzen, so dass diese Singleton -Schreibmethode nicht verwendet wird. Ähnliche Methoden umfassen:
öffentliche Klasse Singleton {public static Final Singleton Instance = new Singleton (); // Singleton mit öffentlichem Final Field Private Singleton () {}} // <effektives Java> Seite 14 zeigt den Unterschied zwischen den beidenDouble-Check Lock + Vulatile (LAZYLAD, Gewindesicher, aber dunkel)
Das doppelt geprüfte Verriegelungsmuster ist eine Verriegelungsmethode unter Verwendung von Synchronblöcken. Programmierer nennen es eine Doppelprüfsperrung, da zwei Check -Instanz == NULL vor dem Synchronisationsblock und einmal innerhalb des Synchronisationsblocks vorliegt. Warum müssen wir im Synchronisationsblock erneut überprüfen? Da mehrere Threads eingeben können, wenn außerhalb des Synchronisationsblocks zusammen eine sekundäre Überprüfung im Synchronisationsblock durchgeführt wird, werden mehrere Instanzobjekte generiert.
public static singleton gotsingleton () {if (instance == null) {// Single Checked Synchronized (Singleton.class) {if (instance == null) {// double checked instance = new Singleton (); }}} return Instance;}Dieser Code sieht perfekt aus, ist aber leider problematisch. Die Hauptsache ist die Satzinstanz = new Singleton (). Dies ist keine Atomoperation. Tatsächlich macht dieser Satz in JVM ungefähr die folgenden 3 Dinge.
Es gibt jedoch eine Optimierung der Anordnung der Anweisungen im JIT -Compiler von JVM. Mit anderen Worten, die Reihenfolge der obigen zweiten und dritten Schritte kann nicht garantiert werden, und die endgültige Ausführungsreihenfolge kann 1-2-3 oder 1-3-2 betragen. Wenn es sich um das letztere handelt, wird es durch Thread 2 vorgegeben, bevor die Ausführung von 3 und 2 nicht ausgeführt wird. Zu diesem Zeitpunkt ist die Instanz bereits nicht null (aber nicht initialisiert), sodass Thread 2 die Instanz direkt zurückgibt, sie dann verwendet und dann natürlich einen Fehler melden. Dazu müssen wir die Instanzvariable als volatil deklarieren.
öffentliche Klasse Singleton {private volatile statische Singleton -Instanz; // als volatile private Singleton () {} public static singleton gotsingleton () {if (instance == null) {synchronized (Singleton.class) {if (instance == null) {Instance = new Singleton (); }} return Instance; }}Es ist jedoch wichtig zu beachten, dass es immer noch Probleme mit der doppelten Überprüfung der volatilen Versionen in Versionen vor Java 1.5 gibt. Dieses Problem wurde nur in Java 1.5 behoben, sodass Sie danach volatile verwenden können.
Statische innere Klasse: IODH, Initialisierung-auf-Nachfrageinhaber
Dieses Muster kombiniert die statischen internen Klassen von Java und die Multi-Thread-Standard-Synchronisationssperrwissen und implementiert sowohl die Latenzbelastung als auch die Sicherheit von Faden geschickt.
öffentliche Klasse Singleton {private Singleton () {} private statische Klasse Lazyholder {private statische Finale Singleton Instance = new Singleton (); } public static singleton getInstance () {// von Wikipedia return Lazyholder.instance; }}Eine statische innere Klasse entspricht dem statischen Teil ihrer äußeren Klasse. Seine Objekte hängen nicht von externen Klassenobjekten ab, sodass sie direkt erstellt werden können. Statische interne Klassen werden nur dann reproduziert, wenn sie zum ersten Mal verwendet werden.
Multithread -Standardsynchronisationsschloss
Wie wir alle wissen, ist es in der Entwicklung von Multi-Threaden, um das Problem der Parallelität zu lösen, hauptsächlich mit Synchronisierungen zum Hinzufügen von Mutexen für die Synchronisationskontrolle. In einigen Fällen führt der JVM jedoch bereits implizit eine Synchronisation für Sie durch, und in diesen Fällen müssen keine Synchronisationsregelung manuell durchgeführt werden. Diese Situationen umfassen :
1. Bei der Initialisierung von Daten durch einen statischen Initialisierer (Initialisierer auf einem statischen Feld oder in einem statischen {} Block)
2. Beim Zugriff auf das endgültige Feld
3. beim Erstellen eines Objekts vor dem Erstellen eines Threads
4. Wenn der Thread das Objekt sehen kann, wird er verarbeitet
Aufreum
Ab Java 1.5 schreiben Sie einfach einen Enum -Typ, der ein einzelnes Element enthält:
public enum singleton {instance;}Diese Methode ähnelt funktional der öffentlichen Domänenmethode, ist jedoch prägnanter und bietet einen Serialisierungsmechanismus kostenlos, wodurch die mehrfache Instanziierung absolut verhindert wird, selbst wenn sie komplexe Serialisierungs- oder Reflexionsangriffe gegenübersehen. Obwohl dieser Ansatz nicht weit verbreitet ist, sind die Aufzählungstypen einzelner Elemente der beste Weg, Singleton zu implementieren.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.Was sind die Details des statischen Finales?
2. Ist die Zuordnungsinitialisierung im statischen Feld nacheinander und im statischen Codeblock?
3.. So schreiben Sie ein Singleton -Muster für statische interne Klassen
4. Haben Sie die Beispiele in der Java EE -Entwurfsmusteranalyse und -Anwendung wirklich einen faulen Ladungseffekt?
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels für das Studium oder die Arbeit eines jeden hilfreich sein wird. Ich hoffe auch, Wulin.com mehr zu unterstützen!