当前位置:网站首页>Connaissez - vous les sept types d'écriture du modèle Singleton?

Connaissez - vous les sept types d'écriture du modèle Singleton?

2021-09-15 07:41:23 Tarzan d'Ali

Bonjour tout le monde,C'est moi.Un test pour tout le monde:"Un seul exemple du mode Singleton,Comment écrire?"

"N'est - ce pas la privatisation des méthodes de construction?"

”Oui, oui.!……Il y a sept façons d'écrire le modèle Singleton,Tu sais quoi??“


Revenons à nos moutons……

Mode Singleton(Singleton Pattern)On peut dire que c'est le modèle de conception le plus simple.

Utilisez un idiome pour décrire le modèle Singleton——“Il n'y a pas deux jours,Il n'y a pas deux maîtres”.

Votre roi,La folie infinie

Qu'est - ce que ça veut dire?C'est le processus actuel qui garantit qu'une classe n'a qu'une seule instance globale.

Quel est l'avantage du modèle Singleton?[1]

  • Le mode Singleton n'a qu'une seule instance en mémoire,Réduction des dépenses de mémoire
  • Le mode Singleton ne génère qu'une seule instance,Cela réduit les frais généraux de performance du système
  • Le mode Singleton évite l'utilisation multiple des ressources
  • Le mode Singleton permet de définir des points d'accès globaux dans le système

Est - ce que le mode Singleton est une balle d'argent?Y a - t - il des défauts?

  • Le mode Singleton n'a généralement pas d'interface,L'extension est difficile
  • Le mode Singleton n'est pas propice à l'essai
  • Le modèle à cas unique est en conflit avec le principe de la responsabilité unique

Dans quel cas utiliser le mode Singleton?

  • Environnement nécessitant un numéro de série unique
  • Un point d'accès partagé ou des données partagées sont nécessaires tout au long du projet
  • Trop de ressources sont nécessaires pour créer un objet
  • Un grand nombre de constantes statiques et de méthodes statiques doivent être définies(Comme les outils)L'environnement de

Et puis..., Entrez dans le thème d'aujourd'hui , Regardons sept façons d'écrire le modèle Singleton !

1、Type affamé(Sécurité des fils)

public class Singleton_1 {

    private static Singleton_1 instance=new Singleton_1();

    private Singleton_1() {
    }

    public static Singleton_1 getInstance() {
        return instance;
    }

}

Type affamé,Comme son nom.,La faim n'importe quoi, Initialisation directe lors de la définition .

Parce queinstance C'est une variable statique , Donc il termine l'Instanciation quand la classe est chargée ,Il n'y a pas de problème de sécurité du fil.

Ce n'est pas une façon paresseuse de charger , Que nos programmes soient utilisés ou non , Il est initialisé au début du programme .

Donc nous avons une autre façon de

2、Paresseux(Thread Unsafe)

public class Singleton_2 {

    private static Singleton_2 instance;

    private Singleton_2() {
    }

    public static Singleton_2 getInstance() {
        if (instance == null) {
            instance = new Singleton_2();
        }
        return instance;
    }

}

Paresseux Qu'est - ce que? Charge seulement quand elle est utilisée , Cela nous permet de réaliser le chargement paresseux que nous pensons .

Mais!

Il introduit de nouveaux problèmes ?Quel est le problème??Problèmes de sécurité des fils.

 Les fils paresseux ne sont pas sûrs

Les photos sont aussi claires , En cas de Multithreading , Il peut y avoir un tel problème :

Un thread juge instance==null, Démarrer l'initialisation de l'objet ;

Avant d'initialiser l'objet , Accès par un autre thread ,Jugementinstance==null, Créer des objets aussi .

Résultats finaux, Est d'instancier deux SingletonObjet.

Ce n'est pas notre cas ?Et alors??

3、Paresseux(Verrouillage)

public class Singleton_3 {

    private static Singleton_3 instance;

    private Singleton_3() {
    }

    public synchronized static Singleton_3 getInstance() {
        if (instance == null) {
            instance = new Singleton_3();
        }
        return instance;
    }
}

L'approche la plus directe , Verrouillez - le directement !

Mais cette méthode directe de verrouillage , Tous les accès nécessitent un verrouillage , Il en résulte un gaspillage de ressources .

Et alors??

4、Paresseux(Verrouillage à double contrôle)

public class Singleton_4 {
    //volatileModification,Empêcher le réarrangement des commandes
    private static volatile Singleton_4 instance;

    private Singleton_4() {
    }

    public static Singleton_4 getInstance() {
        // Première vérification , Vérifier si l'Instance existe 
        if (instance == null) {
            //Bloc de synchronisation
            synchronized (Singleton_4.class) {
                // Deuxième vérification , Vérifier si l'Instance existe , Créer une instance si elle n'existe pas 
                if (instance == null) {
                    instance = new Singleton_4();
                }
            }
        }
        return instance;
    }

}

C'est l'un des plus recommandés ,Verrouillage à double contrôle.

Où est son progrès ?

On metsynchronized Ajouté à l'intérieur de la méthode , L'accès général n'est pas verrouillé ,Seulement siinstance==null C'est fermé quand .

En attendant, regardons quelques questions clés .

  • Commençons par la première question , Pourquoi la double vérification ?

Réfléchissez tous., Sans double contrôle .

Si les deux Threads appellent ensemble getInstanceMéthodes, Et ils ont tous été jugés pour la première fois instance==null, Alors le premier thread a pris la serrure , Puis instantané instance, Puis il a relâché la serrure , Puis le deuxième fil a eu le fil , Et instantané aussi tout de suite instance. Ce n'est pas notre cas unique .

Passons à la deuxième question ,Pourquoi utiliservolatile Modification instance?

Nous savons peut - être que la réponse est d'empêcher le réarrangement des instructions .

Alors ce réarrangement fait référence à ?Ça veut direinstance = new Singleton(), Nous avons l'impression d'être un objet instantané en une seule étape ,En fait, pourJVMDirectives, Est divisé en trois étapes :

  1. Allouer de l'espace mémoire
  2. Initialiser l'objet
  3. Pointez l'objet vers l'espace mémoire que vous venez d'allouer

Certains compilateurs pour l'optimisation des performances , Les étapes 2 et 3 pourraient être franchies Réorganisation, L'ordre devient :

  1. Allouer de l'espace mémoire
  2. Pointez l'objet vers l'espace mémoire que vous venez d'allouer
  3. Initialiser l'objet

Réarrangement des instructions

Et alors?,Si non utilisévolatile Que peut - il se passer pour empêcher le réarrangement des instructions ?

 Accès à un objet non initialisé

Dans ce cas,,T7 Le fil du temps BC'est exact.instanceVisites, J'ai visité un Initialisation incomplète Objet de.

Il faut doncinstance Ajouter les mots clés avant volatile.

  • UtilisévolatileAprès mot - clé,C'est garanti.Ordre, Le réarrangement des instructions est interdit ;
  • volatile On peut aussi garantir Visibilité,Java Le modèle de mémoire garantit que les valeurs des variables vues par tous les Threads sont cohérentes .

5、Mode Singleton(Classe interne statique)

public class Singleton_5 {

    private Singleton_5() {
    }

    private static class InnerSingleton {
        private static final Singleton_5 instance = new Singleton_5();
    }

    public static Singleton_5 getInstance() {
        return InnerSingleton.instance;
    }
}

La classe interne statique est une autre façon d'écrire , Il n'y a pas que le chargement paresseux 、Sécurité des fils,EtJVM La capacité d'optimiser les instructions est également maintenue .

SingletonLa classe n'est pas instantanée immédiatement lorsqu'elle est montée,Mais quand l'Instanciation est nécessaire,AppelezgetInstanceMéthodes, Pour charger une classe interne statique InnerSingletonCatégorie,Pour finirSingletonInstanciation de.

Les propriétés statiques de la classe ne sont initialisées que la première fois que la classe est chargée, En même temps, le processus de chargement de classe est mutuellement exclusif ,JVM Ça nous a aidés à sécuriser les fils .

6、Mode Singleton(CAS)

public class Singleton_6 {

    private static final AtomicReference<Singleton_6> INSTANCE = new AtomicReference<Singleton_6>();

    private Singleton_6() {
    }

    public static final Singleton_6 getInstance() {
        //Attendez.
        while (true) {
            Singleton_6 instance = INSTANCE.get();
            if (null == instance) {
                INSTANCE.compareAndSet(null, new Singleton_6());
            }
            return INSTANCE.get();
        }
    }
}

Ce genre deCAS Le mode Singleton de l'équation est une variante de la serrure directe paresseuse ,sychronizedC'est une serrure pessimiste.,EtCAS C'est la serrure optimiste ,Comparaison,Plus léger.

Bien sûr., Ce genre d'écriture est assez rare ,CAS Il y a un problème d'être occupé, etc ,Ça pourrait causerCPU Un gaspillage de ressources .

7、Mode Singleton(Enumeration)

public enum Singleton_7 {

    // Définir une énumération ,Ça représenteSingletonUn exemple de
    INSTANCE;
    public void anyMethod(){
        System.out.println("do any thing");
    }
}

Mode d'appel:

    @Test
    void anyMethod() {
        Singleton_7.INSTANCE.anyMethod();
    }

《Effective Java》 Une façon recommandée par l'auteur , Très simple .

Mais cette écriture résout le problème principal :Sécurité des fils、⾃ Par chaîne ⾏De、Single⼀Exemple.

Résumé

Du point de vue de l'utilisation , Si vous n'avez pas besoin d'un chargement paresseux , C'est un homme affamé ; Si vous avez besoin d'un chargement paresseux , Les classes internes statiques peuvent être considérées , Ou essayez d'énumérer .

Du point de vue de l'entrevue,Paresseux、Type affamé、 Double checklock affamé , Ces trois points sont importants . Le mode de verrouillage à double contrôle doit savoir où est le réarrangement des commandes , Quels sont les problèmes .

版权声明
本文为[Tarzan d'Ali]所创,转载请带上原文链接,感谢
https://chowdera.com/2021/09/20210915073252802q.html

随机推荐