Der Zweck des Singleton -Musters besteht darin, sicherzustellen, dass eine Klasse nur eine Instanz hat und auch einen globalen Zugangspunkt dafür bietet. Um zu verhindern, dass andere Arbeiter unsere Klasse instanziieren,
Sie können einen einzigartigen Konstruktor für diese Klasse erstellen und das sichtbare des Konstruktors auf privat einstellen. Es ist erwähnenswert, dass, wenn wir andere nicht private Konstruktoren erstellen oder wir überhaupt nicht erwähnen, dass die Klasse überhaupt nicht erwähnt wird
Für Konstruktoren können andere Personen unsere Klasse immer noch instanziieren. Wenn wir nicht im Voraus ein Singleton -Objekt erstellen möchten, können wir warten, bis wir das Singleton -Objekt zum ersten Mal verwenden, das heißt,
LAG -Initialisierung. Es gibt zwei Gründe für die Abnutzung der Initialisierung von Singleton -Objekten:
1. Vielleicht haben Sie zur statischen Initialisierungszeit nicht genügend Informationen, wie Sie ein Singleton -Objekt initialisieren können.
2. Der Zweck der Auswahl einer LAG -Initialisierung Singleton kann darin bestehen, auf Ressourcen wie Datenbankverbindungen zu warten, insbesondere in Anwendungen, bei denen dieses Singleton in bestimmten bestimmten Sitzungen nicht erforderlich ist.
Wenn ein Singleton in einer Multithread -Umgebung initialisiert wird, müssen wir darauf achten, dass mehrere Themen gleichzeitig initialisieren.
Normalerweise ist das Singleton -Muster in der Java -Sprache eingebaut:
Lazy Way: Bezieht sich auf die globale Singleton -Instanz, die aufgebaut wird, wenn sie zum ersten Mal verwendet wird. Verzögerungsinitialisierung.
Hungry Man -Methode: Bezieht sich auf die globale Einzelinstanz, die während der Klassenbelastung erstellt wird. Dringende Initialisierung.
1. Hungriger chinesisches Singleton
öffentliche Klasse Singleton1 {private Singleton1 () {} // Definieren Sie Ihre eigene Instanz intern. // Beachten Sie, dass dies privat ist. Private statische Singleton1 Instance = new Singleton1 (); /** * // ** * Hier ist eine statische Methode für den externen Zugriff auf diese Klasse, auf die direkt zugegriffen werden kann * @return */public static Singleton1 getInstance () {return Instance; }}2. Lazy Singleton -Klasse
öffentliche Klasse Singleton2 {private statische Singleton2 Instance = null; /*** // *** Diese Methode ist im Vergleich zu den oben genannten verbessert. Es erfordert nicht jedes Mal, Objekte zu generieren, aber das erste Mal * generiert bei Verwendung Instanzen, was die Effizienz verbessert! * @return */ public static Singleton2 getInstance () {if (instance == null) instance = new Singleton2 (); Rückkehrinstanz; }}Das Folgende sind die wichtigsten Multi-Threading-Probleme. Bei faulen Singletons gibt es kein Problem mit einem einzelnen Threading, aber beim Multi-Threading kann es zwei oder mehr Singletion2-Instanzen geben.
Zum Beispiel: Wenn Thread 1 beurteilt, dass Instanz == NULL TRUE ist, führt Thread 2 beim Scannen der neuen Operation vor der Durchführung der neuen Operation und nach der Durchführung der neuen Operation nur den Urteilsvorgang durch, und die Instanz ist immer noch Null. Daher führt Thread 2 auch die neue Operation durch. Und so weiter gibt es unter hoher Parallelität zwei oder mehr Fälle von Singletion2. Offensichtlich ist das falsch.
Ändern Sie daher den Code wie folgt:
öffentliche Klasse Singleton3 {private static Singleton3 Instance = NULL; /*** // *** Diese Methode ist im Vergleich zu den oben genannten verbessert. Es ist nicht erforderlich, dass das Objekt jedes Mal generiert wird, aber das erste Mal * generiert bei der Verwendung Instanzen, was die Effizienz verbessert! * Um Fehler beim Multi-Threading zu vermeiden, wurde das Synchronisations-Flag hinzugefügt * @return */ public static synchronisierte Singleton3 getInstance () {if (instance == null) instance = new Singleton3 (); Rückkehrinstanz; }}Aber dies schafft ein weiteres Problem. Die Methoden werden jedes Mal synchronisiert, wenn die Instanz abgerufen wird. Offensichtlich ist die Leistung sehr betroffen. Ändern Sie also den Code weiter wie folgt:
Völlig, ersetzen Sie die Synchronisation durch geringere Kosten
Warum ist flüchtig billiger als die Synchronisation?
Die Kosten für die Synchronisation werden hauptsächlich durch den Abdeckungsbereich bestimmt. Wenn der Abdeckungsbereich der Synchronisation reduziert werden kann, kann die Programmleistung erheblich verbessert werden.
Die Abdeckung von flüchtigem liegt nur auf variabler Ebene. Daher sind seine Synchronisationskosten sehr niedrig.
Was ist das Prinzip des volatilen?
Die Semantik von Volatile besteht tatsächlich darin, dem Prozessor zu sagen, dass er mich nicht in das Arbeitsgedächtnis versetzen soll. Bitte betreiben Sie mich direkt im Hauptspeicher. (Weitere Informationen finden Sie im Java -Speichermodell für Arbeitsspeicher.)
Wenn Multi-Core- oder Multi-Threading auf die Variable zugreift, betreiben sie daher direkt den Hauptspeicher, der im Wesentlichen eine variable Freigabe erreicht.
Was sind die Vorteile von volatilen?
1. Größerer Programmdurchsatz
2. weniger Code zur Implementierung von Multi-Threading
3. Das Programm hat eine bessere Skalierbarkeit
4. Es ist einfacher zu verstehen und es besteht keine Notwendigkeit für zu hohe Lernkosten.
Was sind die Nachteile von flüchtigem?
1. Anfällig für Probleme
2. Es ist schwer zu entwerfen
Volatile verwendet JDK, die Version 1.5 und höher benötigt.
Der verbesserte Code ist wie folgt (auch als Double Lock bezeichnet):
öffentliche Klasse Singleton4 {private statische volatile Singleton4 -Instanz; /*** // *** Doppelsperrung, um eine Multi-Threading-Anwendungs- und Leistungsoptimierung zu erreichen // 3}} return Instance; }}