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.day.singleton.ep; public class myObject {// laden jetzt GetInstance () -Methode ist nicht synchronisiert // Daher können keine Thread-Safe-Probleme auftreten. Return myObject;}} Erstellen Sie eine Thread -Klasse
Paket com.weishiyao.learn.day.singleton.ep; öffentliche Klasse MyThread erweitert Thread {@Overridepublic void run () {System.out.println (myObject.getInstance (). HashCode ());}} Erstellen Sie eine Run -Klasse
paket com.weishiyao.learn.day.singleton.ep; public class run {public static void main (String [] args) {mythead t = new mythead (); myThread t = new mythead (); myThread t = new mythead (); t.start (); t.start (); T.Start (); T.Start (); T.Start (); T.Start (); t.start ();}} Auslaufergebnisse
1 167772895
2 167772895
3 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.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// laden delaying if (myObject! Erstellen Sie eine Thread -Klasse
Paket com.weishiyao.learn.day.singleton.ep; öffentliche Klasse MyThread erweitert Thread {@Overridepublic 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
1 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.day.singleton.ep; public class run {public static void main (String [] args) {mythread t = new mythead (); myThread t = new myThread (); Mythead (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Auslaufergebnisse
1 980258163
2 1224717057
3 1851889404
4 188820504
5 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.day.singleton.ep; öffentliche Klasse myObject {private static myObject; private myObject () {} synchronisiertes öffentliches statisches myObject getInstance () {// Ladevertrieb versuchen {if (myObject). myObject = new myObject (); }} catch (InterruptedException e) {e.printstacktrace ();} return myObject;}} Dieses synchronisierte Synchronisationsschema führt zu zu ineffizient und die gesamte Methode ist gesperrt
Das zweite synchronisierte Nutzungsschema
package com.weishiyao.learn.day.singleton.ep;public class MyObject {private static MyObject myObject;private MyObject() {}public static MyObject getInstance() {// Delay loading try {synchronized (MyObject.class) {if (myObject != null) {} else {// Simulate some preparation before creating an object Thread.sleep (); myObject = new myObject ();}}} catch (InterruptedException e) {e.printstacktrace ();} return myObject;}} 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.day.singleton.ep; öffentliche Klasse myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Deladung des Ladens versuchen {if (myObject! (MyObject.class) {myObject = new myObject ();}}} catch (InterruptedException e) {e.printstacktrace ();} return myObject;}} 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:
1 1224717057
2 971173439
3 1851889404
4 1224717057
5 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.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Deladung des Ladens versuchen {if (myObject! (MyObject.class) {if (myObject == null) {myObject = new myObject ();}}}} catch (interruptedException e) {e.printstacktrace ();} return myObject;}} 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:
1 1224717057
2 1224717057
3 1224717057
4 1224717057
5 1224717057
3.. Verwenden Sie integrierte statische Klassen, um Einzelfälle zu implementieren
Hauptcode
Paket com.weishiyao.learn.day.singleton.ep; public class myObject {// Innere Klassenmethode private statische Klasse myobjectHandler {private static myObject myObject = new myObject ();} public myObject () {} öffentliche statische statische statische statische myobject getinstance () {) {) {) {) {) {) {) {) {) {) {) {) {{) myobjectan.myobject; Thread -Klassencode
Paket com.weishiyao.learn.day.singleton.ep; öffentliche Klasse MyThread erweitert Thread {@Overridepublic void run () {System.out.println (myObject.getInstance (). HashCode ());}} Rennen Sie Klasse
Paket com.weishiyao.learn.day.singleton.ep; public class run {public static void main (String [] args) {mythread t = new mythead (); myThread t = new myThread (); Mythead (); t.start (); t.start (); t.start (); t.start (); t.start (); t.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 lange Serialversionuid = 888l; // interne Klassenmethode private statische statische Klassen MyoBjeChandl {private statische statische statische statische myobjekte myobject (private myobjectler { oder Geschäft
Paket com.weishiyao.learn.day.singleton.ep; import Java.io.file; Import Java.io.fileInputStream; Import Java.io.filenotFoundException; Import Java.io.io.file.fileOutputstream; Importputstream; SareAnDread {public static void main (String [] args) {try {myObject myObject = myObject.getInstance (); FileOutputStream fosref = new FileOutputStream (neue Datei ("myObjectFile.txt"); ObjectOutputStream (Fosref); {e.printstackTrace ();} fileInputStream fisref; try {fisref = new FileInputStream (neue Datei ("myObjectFile.txt"); iOSRef.ReadObject (); iosref.close (); fisref.close (); System.out.println (myObject.hashCode ());} catch (fileNotFoundException e) {E.printstacktrace ();} catch (ioException E) {E. printaCtrace (); {e.printstacktrace ();}}} Ergebnis
1 970928725
2 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!"); Während der Deserialisierung aufgerufen
System.out.println (myObject.readresolve (). HashCode ());
Ergebnis
1 1255301379
2 Die ReadResolve -Methode wurde genannt!
3 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.day.singleton.ep; öffentliche Klasse myObject {private static myObjectinstance = null; private myObject () {Super ();} static {Instance = new MyObject ();} öffentliches statisches MyObject GetInstance () {return Instance;}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} Thread -Klasse
Paket com.weishiyao.learn.day.singleton.ep; öffentliche Klasse MyThread erweitert Thread {@Overridepublic void run () {für (int i =; i ++) {System.out.println (myObject.getInstance (). Rennen Sie Klasse
Paket com.weishiyao.learn.day.singleton.ep; public class run {public static void main (String [] args) {mythread t = new mythead (); myThread t = new myThread (); Mythead (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Auslaufergebnisse:
1 1678885403
2 1678885403
3 1678885403
4 1678885403
5 1678885403
6 1678885403
7 1678885403
8 1678885403
9 1678885403
10 1678885403
11 1678885403
12 1678885403
13 1678885403
14 1678885403
15 1678885403
16 1678885403
17 1678885403
18 1678885403
19 1678885403
20 1678885403
21 1678885403
22 1678885403
23 1678885403
24 1678885403
25 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.day.singleton.ep; Import Java.sql.Connection; Import Java.Sql.DriverManager; Import Java.SQL.SQLEXCECTION; public enum myObject {ConnectionFactory; private Verbindung; private myobject () -System. "jdbc:mysql://...:/wechat_?useUnicode=true&characterEncoding=UTF-";String name = "root";String password = "";String driverName = "com.mysql.jdbc.Driver";Class.forName(driverName);connection = DriverManager.getConnection(url, name, password);} catch (ClassNotFoundException e) oder Thread -Klasse
Paket com.weishiyao.learn.day.singleton.ep; öffentliche Klasse Mythead erweitert Thread {@Overridepublic void run () {für (int i =; i ++) {System.out.println (myObject.connectionFactory.getConnection (). Rennen Sie Klasse
Paket com.weishiyao.learn.day.singleton.ep; public class run {public static void main (String [] args) {mythread t = new mythead (); myThread t = new myThread (); Mythead (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Auslaufergebnisse
1 Das MyObject -Konstrukt wurde genannt
2 56823666
3 56823666
4 56823666
5 56823666
6 56823666
7 56823666
8 56823666
9 56823666
10 56823666
11 56823666
12 56823666
13 56823666
14 56823666
15 56823666
16 56823666
17 56823666
18 56823666
19 56823666
20 56823666
21 56823666
22 56823666
23 56823666
24 56823666
25 56823666
26 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.day.singleton.ep; Import Java.sql.Connection; Import Java.Sql.DriverManager; Import Java.sql.sqLexception; öffentliche Klasse myObject {public enum myenumsingleton {connectionfactory; private connection; private connection; private connection; private connection; private connection; private connection; private connection; von myObject wurde "); String url =" jdbc: mysql: // ...:/wechat_? useUnicode = true & charakteristischesCoding = utf- "; String name =" root "; String passwart =" "; String drivername =" com.mysql.jdbc.driver "; catch (classNotFoundException e) {e.printstacktrace ();} catch (sqlexception e) {e.printstacktrace ();}} public Connection getConnection () {return connection;}} public static Connection getConnection () {return myEnumsingleton.connectionFactory.getConnection (); Ändern Sie den Threadcode
Paket com.weishiyao.learn.day.singleton.ep; öffentliche Klasse MyThread erweitert Thread {@Overridepublic void run () {für (int i =; i ++) {System.out.println (myObject.getConnection (). Ergebnis
1 Das MyObject -Konstrukt wurde genannt
2 1948356121
3 1948356121
4 1948356121
5 1948356121
6 1948356121
7 1948356121
8 1948356121
9 1948356121
10 1948356121
11 1948356121
12 1948356121
13 1948356121
14 1948356121
15 1948356121
16 1948356121
17 1948356121
18 1948356121
19 1948356121
20 1948356121
21 1948356121
22 1948356121
23 1948356121
24 1948356121
25 1948356121
26 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.