concept:
Le singleton singleton en Java est un modèle de conception commun. Le singleton singleton est divisé en trois types: Singleton paresseux, singleton affamé et singleton enregistré.
Le mode singleton a les caractéristiques suivantes:
1. Il ne peut y avoir qu'une seule instance dans une classe singleton.
2. La classe Singleton doit créer sa propre instance unique.
3. La classe Singleton doit fournir cette instance à tous les autres objets.
Le modèle Singleton garantit qu'une classe n'a qu'une seule instance et l'instancie elle-même et fournit cette instance à l'ensemble du système. Dans les systèmes informatiques, les objets de pilote pour les pools de threads, les caches, les objets journaliers, les boîtes de dialogue, les imprimantes et les cartes graphiques sont souvent conçues comme des singletons. Ces applications ont plus ou moins la fonctionnalité d'un gestionnaire de ressources. Chaque ordinateur peut avoir plusieurs imprimantes, mais un seul bobineur d'imprimante peut être disponible pour éviter que deux travaux d'impression soient sortis à l'imprimante en même temps. Chaque ordinateur peut avoir plusieurs ports de communication, et le système doit gérer de manière centralisée ces ports de communication pour éviter qu'un port de communication soit appelé simultanément par deux demandes. En bref, le choix d'un modèle singleton est d'éviter les États incohérents et d'éviter une influence politique.
Voici deux types de présentations: paresseux et affamé
1. Chargement de style immédiatement / affamé
Avant d'appeler la méthode, l'instance a été créée, code:
package com.weishiyao.learn.day8.singleton.ep1; classe publique MyObject {// Chargement maintenant == Mode maléfique privé statique myObject = new myObject (); MyObject privé () {} public static myObject getInstance () {// Cette version de code charge maintenant // L'inconvénient de cette version du code est qu'il ne peut pas y avoir d'autres variables d'instance // parce que la méthode getInstance () n'est pas synchronisée // Par conséquent, les problèmes non-thread-sié peuvent se produire MyObject; }} Créer une classe de threads
package com.weishiyao.learn.day8.singleton.ep1; public class MyThread étend Thread {@Override public void run () {System.out.println (myObject.getInstance (). HashCode ()); }} Créer une classe d'exécution
package com.weishiyao.learn.day8.singleton.ep1; classe publique run {public static void main (String [] args) {mythread t1 = new mythread (); Mythread t2 = new mythread (); Mythread t3 = new mythread (); t1.start (); t2.start (); t3.start (); }} Résultats en cours d'exécution
167772895
167772895
167772895
HashCode est la même valeur, ce qui signifie que l'objet est également le même, ce qui signifie que le mode de chargement instantané est implémenté.
2. Chargement paresseux / paresseux
L'instance sera créée une fois la méthode appelée. Le plan d'implémentation peut être de mettre une instanciation dans le constructeur sans paramètre, de sorte qu'une instance de l'objet ne sera créée que lorsque la méthode est appelée. Code:
package com.weishiyao.learn.day8.singleton.ep2; classe publique myObject {private static myObject myObject; MyObject privé () {} public static myObject getInstance () {// Delay chargement if (myObject! = null) {} else {myObject = new myObject (); } return myObject; }} Créer une classe de threads
package com.weishiyao.learn.day8.singleton.ep2; public class Mythread étend Thread {@Override public void run () {System.out.println (myObject.getInstance (). HashCode ()); }} Créer une classe d'exécution
package com.weishiyao.learn.day8.singleton.ep2; classe publique run {public static void main (String [] args) {mythread t1 = new mythread (); t1.start (); }}Résultats en cours d'exécution
167772895
Bien qu'une instance d'un objet soit prise, si elle se trouve dans un environnement multi-thread, plusieurs instances se produiront, ce qui n'est pas un modèle singleton
Exécutez la classe de test
package com.weishiyao.learn.day8.singleton.ep2; classe publique run {public static void main (String [] args) {mythread t1 = new mythread (); 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 (); }}Résultats en cours d'exécution
980258163
1224717057
1851889404
188820504
1672864109
Puisqu'il y a un problème, nous devons résoudre le problème. Solution multithread en mode paresseux, code:
La première solution, le plus souvent, ajouter synchronisé et synchronisée peut être ajoutée à différentes positions
La première méthode verrouille
package com.weishiyao.learn.day8.singleton.ep3; classe publique myObject {private static myObject myObject; MyObject privé () {} Synchronisé public static MyObject GetInstance () {// Delay Chargement Try {if (myObject! = null) {} else {// Simuler une certaine préparation avant de créer un thread d'objet.Sleep (2000); myObject = new myObject (); }} catch (InterruptedException e) {e.printStackTrace (); } return myObject; }}Ce schéma de synchronisation synchronisé se traduit par trop inefficace et toute la méthode est verrouillée
Le deuxième schéma d'utilisation synchronisé
package com.weishiyao.learn.day8.singleton.ep3; classe publique myObject {private static myObject myObject; MyObject privé () {} public static myObject getInstance () {// Delay chargement try {synchronisé (myObject.class) {if (myObject! = null) {} else {// Simuler un travail de préparation avant de créer un objet Thread.Sleep (2000); myObject = new myObject (); }}} catch (InterruptedException e) {e.printStackTrace (); } return myObject; }} Cette méthode est également très faible en efficacité. Tous les codes de la méthode sont verrouillés. Vous n'avez qu'à verrouiller le code de clé. Le troisième plan d'utilisation synchronisé
Package com.weishiyao.learn.day8.singleton.ep3;
classe publique MyObject {MyObject statique privé MyObject; MyObject privé () {} public static myObject getInstance () {// Delay chargement try {if (myObject! = null) {} else {// simule une certaine préparation avant de créer le thread d'objet.Sleep (2000); synchronisé (myObject.class) {myObject = new MyObject (); }}} catch (InterruptedException e) {e.printStackTrace (); } return myObject; }}Cela semble être la meilleure solution, mais après l'avoir exécutée, j'ai trouvé que c'est en fait un non-thread-sate
résultat:
1224717057
971173439
1851889404
1224717057
1672864109
Pourquoi?
Bien que l'instruction qui crée un objet soit verrouillée, un seul thread peut compléter la création à la fois, une fois que le premier thread est entré pour créer l'objet objet, le deuxième thread peut toujours continuer à le créer, car nous verrouillons uniquement l'instruction de création, cette solution problématique Solution Problème
package com.weishiyao.learn.day8.singleton.ep3; classe publique myObject {private static myObject myObject; MyObject privé () {} public static myObject getInstance () {// Delay chargement try {if (myObject! = null) {} else {// simule une certaine préparation avant de créer un thread d'objet.Sleep (2000); synchronisé (myObject.class) {if (myObject == null) {myObject = new MyObject (); }}}} catch (InterruptedException e) {e.printStackTrace (); } return myObject; }}Il suffit d'ajouter un autre jugement à la serrure pour assurer un singleton. Ceci est le mécanisme DCL à double vérification
Les résultats sont les suivants:
1224717057
1224717057
1224717057
1224717057
1224717057
3. Utilisez des classes statiques intégrées pour implémenter des cas uniques
Code principal
package com.weishiyao.learn.day8.singleton.ep4; classe publique MyObject {// Méthode de classe interne Méthode privée classe statique MyObjecthandler {private static myObject myObject = new MyObject (); } public myObject () {} public static myObject getInstance () {return myobjecthandler.myObject; }} Code de classe de thread
package com.weishiyao.learn.day8.singleton.ep4; public class Mythread étend Thread {@Override public void run () {System.out.println (myObject.getInstance (). HashCode ()); }} Classe de course
package com.weishiyao.learn.day8.singleton.ep4; classe publique run {public static void main (string [] args) {mythread t1 = new mythread (); 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 (); }}résultat
1851889404
1851889404
1851889404
1851889404
1851889404
Grâce à des classes statiques internes, un motif de singleton en filetage est obtenu
Iv. Sérialiser et désérialiser les modèles singleton
Les classes statiques intégrées peuvent atteindre des problèmes de sécurité du thread, mais si vous rencontrez des objets sérialisés, le résultat obtenu en utilisant la méthode par défaut est toujours plusieurs cas.
Code MyObject
package com.weishiyao.learn.day8.singleton.ep5; import java.io.serializable; public class myObject implémente serializable {/ ** * * / private static final SerialVersionUID = 888l; // Méthode de classe intérieure Méthode privée statique MyoBjecthandler {private static myObject MyObject = new MyObject (); } public myObject () {} public static myObject getInstance () {return myobjecthandler.myObject; } // MyObject ReadResolve () {// System.out.println ("La méthode ReadResolve a été appelée!"); // return myobjecthandler.myobject; //}} Entreprise
Package com.weishiyao.learn.day8.singleton.ep5; import java.io.file; import java.io.fileinputStream; import java.io.filenotfoundException; import java.io.fileoutputStream; import java.io.ioException; import java.io.objectInputStream; import java.io. classe SAVEANDREAD {public static void main (String [] args) {try {myObject myObject = myObject.getInstance (); FileoutputStream fosref = new FileOutputStream (nouveau fichier ("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 (nouveau fichier ("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 (); }}}résultat
970928725
1099149023
Deux codes de hash différents prouvent qu'ils ne sont pas le même objet. Solution, ajoutez le code suivant
protégé myObject readResolve () {System.out.println ("La méthode ReadResolve a été appelée!"); retourner myobjecthandler.myObject; }Appelé pendant la désérialisation, vous pouvez obtenir le même objet
System.out.println (myObject.ReadResolve (). HashCode ());
résultat
1255301379
La méthode ReadResolve a été appelée!
1255301379
Le même code de hachage prouve que le même objet est obtenu
5. Utilisez des blocs de code statique pour implémenter un seul cas
Le code du bloc de code statique est déjà exécuté lors de l'utilisation de la classe, de sorte que la fonctionnalité de code statique rapide peut être utilisée pour implémenter le mode de profit simple.
Classe MyObject
package com.weishiyao.learn.day8.singleton.ep6; classe publique myObject {private static myObject instance = null; MyObject privé () {super (); } static {instance = new myObject (); } public static myObject getInstance () {return instance; }} Classe de threads
package com.weishiyao.learn.day8.singleton.ep6; public class Mythread étend Thread {@Override public void run () {for (int i = 0; i <5; i ++) {System.out.println (myObject.getInstance (). Hashcode ()); }}} Classe de course
package com.weishiyao.learn.day8.singleton.ep6; classe publique run {public static void main (string [] args) {mythread t1 = new mythread (); 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 (); }}Résultats en cours:
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
Le motif Singleton en filetage est obtenu avec succès via la fonctionnalité d'exécution uniquement des blocs de code statique.
6. Utilisez les types de données Enum Enu pour implémenter le mode Singleton
Les caractéristiques de l'énumération d'énumération et des blocs de code statique sont similaires. Lorsque vous utilisez des énumérations, le constructeur sera appelé automatiquement et peut également être utilisé pour implémenter le mode Singleton.
Classe MyObject
package com.weishiyao.learn.day8.singleton.ep7; import java.sql.connection; import java.sql.driverManager; import java.sql.sqlexception; public enum myoBject {connectionFactory; connexion de connexion privée; MyObject privé () {try {System.out.println ("La construction de MyObject a été appelée"); String url = "jdbc: mysql: //172.16.221.19: 3306 / weChat_1? Useunicode = true & caractérisation = utf-8"; String name = "root"; Chaîne mot de passe = "111111"; String drivername = "com.mysql.jdbc.driver"; Class.forname (drivername); connexion = driverManager.getConnection (URL, nom, mot de passe); } catch (classNotFoundException e) {e.printStackTrace (); } catch (sqlexception e) {e.printStackTrace (); }} Connexion publique getConnection () {Return Connection; }} Classe de threads
package com.weishiyao.learn.day8.singleton.ep7; public class Mythread étend Thread {@Override public void run () {for (int i = 0; i <5; i ++) {System.out.println (myObject.ConnectionFactory.getConnection (). HashCode ()); }}} Classe de course
package com.weishiyao.learn.day8.singleton.ep7; classe publique run {public static void main (string [] args) {mythread t1 = new mythread (); 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 (); }}Résultats en cours d'exécution
Appelé la construction MyObject
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
La méthode d'écriture ci-dessus expose la classe d'énumération, qui viole le "principe de responsabilité unique". Vous pouvez utiliser une classe pour envelopper l'énumération.
Package com.weishiyao.learn.day8.singleton.ep8; import java.sql.connection; import java.sql.driverManager; import java.sql.sqlexception; public class myobject {public enum myenumsingleton {connectionFactory; connexion de connexion privée; MyEnumsIngleton privé () {try {System.out.println ("La construction de MyObject a été appelée"); String url = "jdbc: mysql: //172.16.221.19: 3306 / weChat_1? Useunicode = true & caractérisation = utf-8"; String name = "root"; Chaîne mot de passe = "111111"; String drivername = "com.mysql.jdbc.driver"; Class.forname (drivername); connexion = driverManager.getConnection (URL, nom, mot de passe); } catch (classNotFoundException e) {e.printStackTrace (); } catch (sqlexception e) {e.printStackTrace (); }} Connexion publique getConnection () {Return Connection; }} Connexion statique publique getConnection () {return myEnumsingleton.connectionfactory.getConnection (); }} Modifier le code du thread
package com.weishiyao.learn.day8.singleton.ep8; public class Mythread étend Thread {@Override public void run () {for (int i = 0; i <5; i ++) {System.out.println (myObject.getConnection (). HashCode ()); }}} En conséquence, la construction MyObject est appelée
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
Ce qui précède résume diverses situations et solutions rencontrées lors de la combinaison du mode d'intérêt unique avec le multi-threading, afin qu'il puisse être examiné lorsqu'il est utilisé plus tard.