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.day.singleton.ep; classe publique MyObject {// Chargement Now == Mode maléfique Private Static MyObject MyObject = new MyObject (); Private MyObject () {} public static MyObject GetInstance () {// Ce code ne peut pas être le chargement // le désavantage de cette version de la version du code est ce qu'il y a de la version Varie // le désavantage de cette version de la Code est ce qu'il y a de la version Varie // le désavantage de cette version de la Code est ce que le code est autrement VaIaBles // Le désavantage de cette version de la Code est ce qu'il y a autre exemple La méthode getInstance () n'est pas synchronisée // Par conséquent, les problèmes non-thread peuvent se produire Retour MyObject;}} Créer une classe de threads
package com.weishiyao.learn.day.singleton.ep; public class MyThread étend Thread {@OverRidePublic void run () {System.out.println (myObject.getInstance (). HashCode ());}} Créer une classe d'exécution
package com.weishiyao.learn.day.singleton.ep; classe publique Run {public static void main (String [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); t.start (); t.start (); t.start (); t.start ();}} Résultats en cours d'exécution
1 167772895
2 167772895
3 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.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Delay chargement if (myObject! = null) {} else {myObject = new MyObject ();} Retourne MyObject;}} Créer une classe de threads
package com.weishiyao.learn.day.singleton.ep; public class MyThread étend Thread {@OverRidePublic 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
1 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.day.singleton.ep; classe publique Run {public static void main (String [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Résultats en cours d'exécution
1 980258163
2 1224717057
3 1851889404
4 188820504
5 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.day.singleton.ep; classe publique MyObject {private static myObject MyObject; private myObject () {} synchronisé public static myObject getInstance () {// Delay chargement try {if (myobject! = null) {} else {// simuler une préparation avant la création d'un thread d'objet.);); 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.day.singleton.ep; classe publique MyObject {private static myObject myObject; private myObject () {} public static myobject getInstance () {// Delay chargeing try {synchronized (myobject.class) {if (myobject! = null) {} else {// simule quelque part avant la préparation avant de créer un objet nul Thread.sleep (); 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.day.singleton.ep; classe publique MyObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Delay Loading Try {if (myObject! = null) {} else {// Similate) avant de créer un thread d'objet. {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:
1 1224717057
2 971173439
3 1851889404
4 1224717057
5 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.day.singleton.ep; classe publique MyObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// Delay Chargeing Try {if (myObject! = null) {} else {// Similate work work (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:
1 1224717057
2 1224717057
3 1224717057
4 1224717057
5 1224717057
3. Utilisez des classes statiques intégrées pour implémenter des cas uniques
Code principal
Package com.weishiyao.learn.day.singleton.ep; classe publique MyObject {// 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.myBject;}} Code de classe de thread
package com.weishiyao.learn.day.singleton.ep; public class MyThread étend Thread {@OverRidePublic void run () {System.out.println (myObject.getInstance (). HashCode ());}} Classe de course
package com.weishiyao.learn.day.singleton.ep; classe publique Run {public static void main (String [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.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; classe publique MyObject implémente sérialisable {/ *** * / private static final SerialversionUid = 888l; // class interne method private static class myobJeCThandler {private static Myobject Myobject = new Myobject ();) Public MyObject (privé MyObject MyObject. {} public static myObject getInstance () {return myobjecthandler.myObject;} // protégé myObject readResolve () {// system.out.println ("La méthode ReadResolve a été appelée!"); // return myobjecthandler.myobject; //}} Entreprise
Package com.weishiyao.learn.day.singleton.ep; import java.io.file; import java.io.fileInputStream; import java.io.filenotfoundException; importer java.io.ObjectInputStream; Importer java.io.ioException; Importer java.oobjectInputStream; import java. SAVEANDREAD {public static void main (String [] args) {try {myObject myObject = myObject.getInstance (); fileoutputStream fosref = new FileOutputStream (new File ("myObjectFile.txt")); ObjectOutputStream Oosref = new ObjectOutputStream (fosref); oosref.writeObject (myObject); oosref.close (); fosref.close (); system.out.println (myObject.HashCode ());} catch (filenotfoundException e) gens iOSref.ReadObject (); ioSref.close (); fisref.close (); System.out.println (myObject.HashCode ());} Catch (FileNotFoundException e) {E.PrintStackTrace ();} Catch (Classfound E) {E.PrintStackTrace ();} Catch (classNoUNExe {e.printStackTrace ();}}} résultat
1 970928725
2 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!"); return myobjecthandler.myObject;} Appelé pendant la désérialisation, vous pouvez obtenir le même objet
System.out.println (myObject.ReadResolve (). HashCode ());
résultat
1 1255301379
2 La méthode ReadResolve a été appelée!
3 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.day.singleton.ep; public class myObject {private static myObject instance = null; private myObject () {super ();} static {instance = new myObject ();} public static myObject getInstance () {return instance;}}} Classe de threads
package com.weishiyao.learn.day.singleton.ep; public class Mythread étend Thread {@OverRidePublic void run () {for (int i =; i <; i ++) {System.out.println (myObject.getInstance (). Hashcode ());}}} Classe de course
package com.weishiyao.learn.day.singleton.ep; classe publique Run {public static void main (String [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Résultats en cours:
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
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.day.singleton.ep; import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; public enum myObject {connectionFactory "JDBC: mysql: // ...: / weChat_? useunicode = true & worseencoding = utf-"; string name = "root"; string password = ""; string drivername = "com.mysql.jdbc.driver"; class.forname (drivername); Connection = dirvermanager.getConnection (url, nom, mot de passe); (ClassNotFoundException e) {e.printStackTrace ();} catch (sqlexception e) {e.printStackTrace ();}} Connexion publique getConnection () {return Connection;}} Classe de threads
package com.weishiyao.learn.day.singleton.ep; public class Mythread étend Thread {@OverRiDepublic void run () {for (int i =; i <; i ++) {System.out.println (myObject.ConnectionFactory.getConnection (). HashCode ()); Classe de course
package com.weishiyao.learn.day.singleton.ep; classe publique Run {public static void main (String [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new MyThread (); t.start (); t.start (); t.start (); t.start (); t.start (); t.start (); }} Résultats en cours d'exécution
1 La construction MyObject a été appelée
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
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.day.singleton.ep; import java.sql.connection; importer java.sql.drivermanager; import java.sql.sqlexception; classe publique myobject {public enumynemsingleton {ConnectionFactory; connexion privée; de MyObject a été appelé "); string url =" jdbc: mysql: // ...: / wechat_? useunicode = true & caractotcoding = utf- "; string name =" root "; string password =" "; string drivername =" com.mysql.jdbc.Grot. mot de passe);} catch (classNotFoundException e) {e.printStackTrace ();} catch (sqlexception e) {e.printStackTrace ();}} Connexion publique getConnection () {return Connection;}} public static static getConnection ();}} Modifier le code du thread
Package com.weishiyao.learn.day.singleton.ep; public class Mythread étend Thread {@OverRidePublic void run () {for (int i =; i <; i ++) {System.out.println (myObject.getConnection (). Hashcode ());}}} résultat
1 La construction MyObject a été appelée
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
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.