Le motif Singleton est de s'assurer qu'une classe n'a qu'une seule instance et fournit également un point d'accès global pour cela. Pour empêcher d'autres travailleurs d'instanier notre classe,
Vous pouvez créer un constructeur unique pour cette classe et définir le visible du constructeur en privé. Il convient de noter que si nous créons d'autres constructeurs non privés, ou si nous ne mentionnons aucune mention de la classe du tout
Pour les constructeurs, alors d'autres personnes peuvent toujours instancier notre classe. Si nous ne voulons pas créer un objet Singleton à l'avance, nous pouvons attendre la première fois que nous utilisons l'objet Singleton, c'est-à-dire,
Initialisation du décalage. Il y a deux raisons pour l'initialisation en retard des objets singleton:
1. Peut-être qu'au moment de l'initialisation statique, vous n'avez pas suffisamment d'informations sur la façon d'initialiser un objet Singleton.
2. Le but de sélectionner un singleton d'initialisation de décalage peut être d'attendre des ressources telles que les connexions de base de données, en particulier dans les applications où ce singleton n'est pas requis dans certaines sessions spécifiques.
Si un singleton est initialisé dans un environnement multithread, nous devons être prudents pour empêcher plusieurs threads d'initialiser le même temps.
Habituellement, le singleton est construit en langue java:
Pazy Way: fait référence à l'instance de singleton mondiale en cours de construction lorsqu'elle est utilisée pour la première fois. Initialisation de retard.
Méthode Hungry Man: fait référence à l'instance unique globale en cours de construction pendant le chargement des cours. Initialisation urgente.
1. Singleton chinois affamé
classe publique singleton1 {private singleton1 () {} // Définissez votre propre instance en interne. // Notez que c'est privé. Instance privée statique singleton1 = new singleton1 (); / ** * // ** * Voici une méthode statique pour l'accès externe à cette classe, qui peut être directement accessible * @return * / public static singleton1 getInstance () {return instance; }}2. Classe de singleton paresseux
classe publique singleton2 {instance privée statique singleton2 = null; / ** * // ** * Cette méthode est améliorée par rapport à ce qui précède. Il ne nécessite pas de génération d'objets à chaque fois, mais la première fois * génère des instances lorsqu'il est utilisé, ce qui améliore l'efficacité! * @return * / public static singleton2 getInstance () {if (instance == null) instance = new singleton2 (); retour d'instance; }}Voici les principaux problèmes multiples. Dans les singletons paresseux, il n'y a aucun problème avec le threading unique, mais lors du multi-threading, il peut y avoir deux instances Singletion2 ou plus.
Par exemple: lorsque Thread 1 juge, cette instance == null est vraie, lors de la numérisation de la nouvelle opération, avant d'effectuer la nouvelle opération et après avoir effectué la nouvelle opération, Thread 2 effectue simplement l'opération de jugement, et l'instance est toujours nul. Par conséquent, Thread 2 effectuera également la nouvelle opération. Et ainsi de suite, sous une grande concurrence, il peut y avoir deux cas ou plus de Singletion2. De toute évidence, c'est incorrect.
Par conséquent, modifiez le code comme suit:
classe publique singleton3 {instance privée statique singleton3 = null; / ** * // ** * Cette méthode est améliorée par rapport à ce qui précède. Il ne nécessite pas que l'objet soit généré à chaque fois, mais la première fois * génère des instances lorsqu'elle est utilisée, ce qui améliore l'efficacité! * Afin d'éviter les erreurs de multi-threading, l'indicateur de synchronisation a été ajouté * @return * / public static synchronisé singleton3 getInstance () {if (instance == null) instance = new singleton3 (); retour d'instance; }}Mais cela crée un autre problème. Les méthodes sont synchronisées chaque fois que l'instance est récupérée. De toute évidence, les performances sont très affectées, alors continuez à modifier le code comme suit:
volatile, remplacez la synchronisation par un coût inférieur
Pourquoi volatile est-il moins cher que la synchronisation?
Le coût de la synchronisation est principalement déterminé par sa plage de couverture. Si la plage de couverture de la synchronisation peut être réduite, les performances du programme peuvent être considérablement améliorées.
La couverture du volatile n'est qu'au niveau variable. Par conséquent, son coût de synchronisation est très faible.
Quel est le principe de volatile?
La sémantique de volatile doit en fait dire au processeur de ne pas me mettre en mémoire de travail, veuillez me faire fonctionner directement dans la mémoire principale. (Voir le modèle de mémoire Java pour la mémoire de travail pour plus de détails)
Par conséquent, lorsque les accès multi-core ou multi-threading accèdent à la variable, ils exploiteront directement la mémoire principale, qui atteint essentiellement le partage de variables.
Quels sont les avantages de la volatile?
1. débit du programme plus grand
2. Moins de code pour implémenter
3. Le programme a une meilleure évolutivité
4. Il est plus facile à comprendre et il n'y a pas besoin de coûts d'apprentissage trop élevés.
Quels sont les inconvénients de la volatile?
1. Sujet aux problèmes
2. Il est difficile de concevoir
Volatile utilise JDK nécessite la version 1.5 et plus.
Le code amélioré est le suivant (également appelé double verrouillage):
classe publique singleton4 {instance privée statique volatile singleton4; / ** * // ** * Double verrouillage pour réaliser des applications multiples et une optimisation des performances * @return * / public static singleton4 getInstance () {if (instance == null) {synchronisé (singleton4.class) {// 1 if (instance == null) // 2 instance = new singleton4 (); // 3}} Instance de retour; }}