Konzept:
Singleton -Muster in Java ist ein gemeinsames Designmuster. Das Singleton -Muster ist in drei Typen unterteilt: Lazy Singleton, Hungry Singleton und registrierter Singleton.
Der Singleton -Modus hat die folgenden Eigenschaften:
1. In einer Singleton -Klasse kann es nur eine Instanz geben.
2. Die Singleton -Klasse muss eine eigene einzigartige Instanz schaffen.
3. Die Singleton -Klasse muss diese Instanz allen anderen Objekten bereitstellen.
Das Singleton -Muster stellt sicher, dass eine Klasse nur eine Instanz hat und sie selbst instanziiert und diese Instanz für das gesamte System bietet. In Computersystemen werden Treiberobjekte für Threadpools, Caches, Protokollobjekte, Dialogfelder, Drucker und Grafikkarten häufig als Singletons entworfen. Diese Anwendungen haben mehr oder weniger die Funktionalität eines Ressourcenmanagers. Jeder Computer kann mehrere Drucker haben, aber es kann nur ein Druckerspooler verfügbar sein, um zu vermeiden, dass zwei Druckaufträge gleichzeitig an den Drucker ausgegeben werden. Jeder Computer kann über mehrere Kommunikationsports verfügen, und das System sollte diese Kommunikationsports zentral verwalten, um zu vermeiden, dass ein Kommunikationsport gleichzeitig von zwei Anfragen aufgerufen wird. Kurz gesagt, die Auswahl eines Singleton -Modells besteht darin, inkonsistente Zustände zu vermeiden und politische Bullität zu vermeiden.
Hier sind zwei Arten von Einführungen: faul und hungrig
1. Laden Sie sofort/hungriger Stil
Vor dem Aufrufen der Methode wurde die Instanz erstellt, Code:
Paket com.weishiyao.learn.day8.singleton.ep1; öffentliche Klasse myObject {// laden jetzt == Evil Mode private statische statische myObject myObject = new myObject (); private myObject () {} public static myObject getInstance () {// Diese Code-Version wird jetzt geladen // Der Nachteil dieser Version des Codes ist, dass es keine anderen Instanzvariablen geben kann //, da die GetInstance () -Methode nicht synchronisiert ist //. }} Erstellen Sie eine Thread -Klasse
Paket com.weishiyao.learn.day8.singleton.ep1; öffentliche Klasse MyThread erweitert Thread {@Override public void run () {System.out.println (myObject.getInstance (). HashCode ()); }} Erstellen Sie eine Run -Klasse
Paket com.weishiyao.learn.day8.singleton.ep1; öffentliche Klasse Run {public static void main (String [] args) {mythread t1 = new mythead (); MyThread t2 = new MyThread (); MyThread t3 = new MyThread (); t1.start (); t2.Start (); t3.Start (); }} Auslaufergebnisse
167772895
167772895
167772895
HashCode ist der gleiche Wert, was bedeutet, dass das Objekt auch das gleiche ist, was bedeutet, dass der sofortige Lademodus implementiert wird.
2. Lazy Loading/Faul
Die Instanz wird erstellt, nachdem die Methode aufgerufen wurde. Der Implementierungsplan kann darin bestehen, Instanziierung in den parameterlosen Konstruktor einzubauen, so dass eine Instanz des Objekts nur dann erstellt wird, wenn die Methode aufgerufen wird. Code:
Paket com.weishiyao.learn.day8.singleton.ep2; öffentliche Klasse myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Ladeverzögerung if (myObject! = null) {} else {myObject = new myObject (); } myObject zurückgeben; }} Erstellen Sie eine Thread -Klasse
Paket com.weishiyao.learn.day8.singleton.ep2; öffentliche Klasse MyThread erweitert Thread {@Override public void run () {System.out.println (myObject.getInstance (). HashCode ()); }} Erstellen Sie eine Run -Klasse
Paket com.weishiyao.learn.day8.singleton.ep2; öffentliche Klasse Run {public static void main (String [] args) {mythread t1 = new mythead (); t1.start (); }}Auslaufergebnisse
167772895
Obwohl eine Instanz eines Objekts genommen wird, treten bei dieser Umgebung mehrere Instanzen auf, was kein Singleton-Muster ist
Führen Sie die Testklasse aus
Paket com.weishiyao.learn.day8.singleton.ep2; öffentliche Klasse Run {public static void main (String [] args) {mythread t1 = new mythead (); MyThread t2 = new MyThread (); MyThread t3 = new MyThread (); MyThread t4 = new MyThread (); MyThread t5 = new MyThread (); t1.start (); t2.Start (); t3.Start (); t4.Start (); t5.Start (); }}Auslaufergebnisse
980258163
1224717057
1851889404
188820504
1672864109
Da es ein Problem gibt, müssen wir das Problem lösen. Multithread -Lösung im faulen Modus, Code:
Die erste Lösung, die am häufigsten synchronisiert und synchronisiert ist, kann zu verschiedenen Positionen hinzugefügt werden
Die erste Methode sperrt
Paket com.weishiyao.learn.day8.singleton.ep3; öffentliche Klasse myObject {private static myObject myObject; private myObject () {} synchronisiertes öffentliches statisches statisches myObject getInstance () {// Delay Loading Try {if (myObject! myObject = new myObject (); }} catch (interruptedException e) {e.printstacktrace (); } myObject zurückgeben; }}Dieses synchronisierte Synchronisationsschema führt zu zu ineffizient und die gesamte Methode ist gesperrt
Das zweite synchronisierte Nutzungsschema
Paket com.weishiyao.learn.day8.singleton.ep3; öffentliche Klasse myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Ladeverzögerung try {synchronized (myObject.class) {if (myObject! myObject = new myObject (); }}} catch (interruptedException e) {e.printstacktrace (); } myObject zurückgeben; }} Diese Methode ist ebenfalls sehr effektiv. Alle Codes in der Methode sind gesperrt. Sie müssen nur den Schlüsselcode sperren. Der dritte synchronisierte Nutzungsplan
Paket com.weishiyao.learn.day8.singleton.ep3;
public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Ladeverzögerung try {if (myObject! synchronisiert (myObject.class) {myObject = new myObject (); }}} catch (interruptedException e) {e.printstacktrace (); } myObject zurückgeben; }}Dies scheint die beste Lösung zu sein, aber nach dem Laufen stellte ich fest, dass es sich tatsächlich nicht um nicht sicher ist
Ergebnis:
1224717057
971173439
1851889404
1224717057
1672864109
Warum?
Obwohl die Anweisung, die ein Objekt erstellt wird, gesperrt ist, kann nur ein Thread die Erstellung gleichzeitig vervollständigen. Nachdem der erste Thread das Objektobjekt erstellt hat, kann der zweite Thread sie weiterhin erstellen, da wir die Erstellungsanweisung nur sperren, diese Problemlösung
Paket com.weishiyao.learn.day8.singleton.ep3; öffentliche Klasse myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Ladeverzögerung try {if (myObject! synchronisiert (myObject.class) {if (myObject == null) {myObject = new myObject (); }}}} catch (interruptedException e) {e.printstacktrace (); } myObject zurückgeben; }}Fügen Sie einfach ein weiteres Urteil zum Schloss hinzu, um einen Singleton zu gewährleisten. Dies ist der DCL -Double Check -Mechanismus
Die Ergebnisse sind wie folgt:
1224717057
1224717057
1224717057
1224717057
1224717057
3.. Verwenden Sie integrierte statische Klassen, um Einzelfälle zu implementieren
Hauptcode
Paket com.weishiyao.learn.day8.singleton.ep4; öffentliche Klasse myObject {// innere Klasse MYOBJECTHANDLER {private static myObject myObject = new MyObject (); } public myObject () {} public static myObject getInstance () {return myobjectHandler.myObject; }} Thread -Klassencode
Paket com.weishiyao.learn.day8.singleton.ep4; öffentliche Klasse MyThread erweitert Thread {@Override public void run () {System.out.println (myObject.getInstance (). HashCode ()); }} Rennen Sie Klasse
paket com.weishiyao.learn.day8.singleton.ep4; öffentliche Klasse Run {public static void main (String [] args) {mythread t1 = new mythead (); MyThread t2 = new MyThread (); MyThread t3 = new MyThread (); MyThread t4 = new MyThread (); MyThread t5 = new MyThread (); t1.start (); t2.Start (); t3.Start (); t4.Start (); t5.Start (); }}Ergebnis
1851889404
1851889404
1851889404
1851889404
1851889404
Durch interne statische Klassen wird ein mit Fadensicher sicherer Singleton-Muster erhalten
Iv. Serialisieren und Deserialisieren von Singleton -Mustern
Eingebaute statische Klassen können Probleme mit der Gewindesicherheit erreichen. Wenn Sie jedoch auf serialisierten Objekten stoßen, ist das Ergebnis, das mit der Standardmethode verwendet wird, immer noch mehrere Fälle.
MyObject Code
Paket com.weishiyao.learn.day8.singleton.ep5; Import Java.io.Serializable; öffentliche Klasse MyObject implementiert serialisierbar { / ** * * / private statische endgültige lange Serialversionuid = 888L; // Innere Klasse Methode private statische Klasse myobjecthandler {private static myObject myObject = new myObject (); } public myObject () {} public static myObject getInstance () {return myobjectHandler.myObject; } // Protected MyObject ReadResolve () {// system.out.println ("Die ReadResolve -Methode wurde genannt!"); // MyobjectHandler.myObject; //}} zurückgeben Geschäft
Paket com.weishiyao.learn.day8.singleton.ep5; Import Java.io.file; Import Java.io.fileinputStream; Import Java.io.filenotFoundException; import Java.io.io.fileOutputStream; ImportStream importieren Java.ioISIO. java.io.objectoutputStream; public class seareNdread {public static void main (String [] args) {try {myObject myObject = myObject.getInstance (); FileOutputStream fosref = new FileOutputStream (neue Datei ("myObjectFile.txt")); ObjectOutputStream OOSREF = new ObjectOutputStream (FOSREF); oosref.writeObject (myObject); oosref.close (); fosref.close (); System.out.println (myObject.hashCode ()); } catch (FilenotFoundException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } FileInputStream fisref; try {fisref = new FileInputStream (neue Datei ("myObjectFile.txt")); ObjectInputStream iOSRef = new ObjectInputStream (FISREF); MyObject myObject = (myObject) iOSRef.ReadObject (); iosref.close (); fisref.close (); System.out.println (myObject.hashCode ()); } catch (FilenotFoundException e) {e.printstacktrace (); } catch (ioException e) {e.printstacktrace (); } catch (classNotFoundException e) {e.printstacktrace (); }}}Ergebnis
970928725
1099149023
Zwei verschiedene Hashcodes beweisen, dass sie nicht dasselbe Objekt sind. Lösung, den folgenden Code hinzufügen
Protected MyObject ReadResolve () {System.out.println ("Die ReadResolve -Methode wurde genannt!"); MyobJectHandler.MyObject zurückgeben; }Während der Deserialisierung aufgerufen
System.out.println (myObject.readresolve (). HashCode ());
Ergebnis
1255301379
Die ReadResolve -Methode wurde genannt!
1255301379
Der gleiche HashCode beweist, dass dasselbe Objekt erhalten wird
5. Verwenden Sie statische Codeblöcke, um Einzelfall zu implementieren
Der Code im statischen Codeblock wird bereits bei der Verwendung der Klasse ausgeführt, sodass die Funktion des statischen Code schnell verwendet werden kann, um den einfachen Gewinnmodus zu implementieren.
MyObject Class
Paket com.weishiyao.learn.day8.singleton.ep6; öffentliche Klasse myObject {private static myObject Instance = null; private myObject () {super (); } static {instance = new myObject (); } public static myObject getInstance () {return Instance; }} Thread -Klasse
Paket com.weishiyao.learn.day8.singleton.ep6; öffentliche Klasse MyThread erweitert Thread {@Override public void run () {für (int i = 0; i <5; i ++) {System.out.println (myObject.getInstance (). HashCode ()); }}} Rennen Sie Klasse
Paket com.weishiyao.learn.day8.singleton.ep6; öffentliche Klasse Run {public static void main (String [] args) {mythread t1 = new mythead (); MyThread t2 = new MyThread (); MyThread t3 = new MyThread (); MyThread t4 = new MyThread (); MyThread t5 = new MyThread (); t1.start (); t2.Start (); t3.Start (); t4.Start (); t5.Start (); }}Auslaufergebnisse:
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
Das thread-safe Singleton-Muster wird erfolgreich durch das Merkmal der einmaligen Ausführung statischer Codeblöcke erhalten.
6. Verwenden Sie Enum -Datentypen, um den Singleton -Modus zu implementieren
Die Eigenschaften von Enum Enum und statischen Codeblöcken sind ähnlich. Bei der Verwendung von Enums wird der Konstruktor automatisch aufgerufen und kann auch zur Implementierung des Singleton -Modus verwendet werden.
MyObject Class
Paket com.weishiyao.learn.day8.singleton.ep7; Import java.sql.connection; import Java.sql.drivermanager; Import Java.sql.sqlexception; public enum myObject {ConnectionFactory; private Verbindungsverbindung; private myObject () {try {System.out.println ("Das Konstrukt von myObject wurde genannt"); String url = "jdbc: mysql: //172.16.221.19: 3306/wechat_1? UseUnicode = true & charakteristischesCoding = utf-8"; String name = "root"; String password = "111111"; String trivername = "com.mysql.jdbc.driver"; Class.Forname (Treibername); connection = driverManager.getConnection (URL, Name, Passwort); } catch (classNotFoundException e) {e.printstacktrace (); } catch (sqlexception e) {e.printstacktrace (); }} public Connection getConnection () {Rückgabeverbindung; }} Thread -Klasse
Paket com.weishiyao.learn.day8.singleton.ep7; öffentliche Klasse MyThread erweitert Thread {@Override public void run () {für (int i = 0; i <5; i ++) {system.out.println (myObject.connectionFactory.getConnection (). HashCode (); }}} Rennen Sie Klasse
Paket com.weishiyao.learn.day8.singleton.ep7; öffentliche Klasse Run {public static void main (String [] args) {mythread t1 = new mythead (); MyThread t2 = new MyThread (); MyThread t3 = new MyThread (); MyThread t4 = new MyThread (); MyThread t5 = new MyThread (); t1.start (); t2.Start (); t3.Start (); t4.Start (); t5.Start (); }}Auslaufergebnisse
Genannt das MyObject -Konstrukt
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
Die obige Schreibmethode enthüllt die Aufzählungsklasse, die gegen das "einzelne Verantwortungsprinzip" verstößt. Sie können eine Klasse verwenden, um die Aufzählung zu wickeln.
Paket com.weishiyao.learn.day8.singleton.ep8; Import Java.sql.Connection; Import Java.SQL.DriverManager; Import Java.sql.sqLexception; öffentliche Klasse MyObject {Public enum myenumsingleton {connectionfactory; private Verbindungsverbindung; private myenumsingleton () {try {System.out.println ("Das Konstrukt von myObject wurde genannt"); String url = "jdbc: mysql: //172.16.221.19: 3306/wechat_1? UseUnicode = true & charakteristischesCoding = utf-8"; String name = "root"; String password = "111111"; String trivername = "com.mysql.jdbc.driver"; Class.Forname (Treibername); connection = driverManager.getConnection (URL, Name, Passwort); } catch (classNotFoundException e) {e.printstacktrace (); } catch (sqlexception e) {e.printstacktrace (); }} public Connection getConnection () {Rückgabeverbindung; }} public static Connection getConnection () {return myenumsingleton.connectionFactory.getConnection (); }} Ändern Sie den Threadcode
Paket com.weishiyao.learn.day8.singleton.ep8; öffentliche Klasse MyThread erweitert Thread {@Override public void run () {für (int i = 0; i <5; i ++) {System.out.println (myObject.getConnection (). HashCode ()); }}} Infolgedessen wird das MyObject -Konstrukt genannt
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
Das obige fasst verschiedene Situationen und Lösungen zusammen, die bei der Kombination des Einzelinteressen-Modus mit Multi-Threading auftreten, sodass er bei späterer Verwendung überprüft werden kann.