Patrones de diseño comunes-01 Patrones de diseño de caso único

  Modelo Singleton: requiere solo una instancia de una clase y proporciona métodos de acceso global.

1. Modelos singleton perezosos y hambrientos

1.1 Slacker

    El patrón de singleton diferido se instancia mediante inicialización estática cuando se carga la clase.

Layzerbones de clase pública {Layzerbones 
    estáticos privados layzer = new Layzerbones (); 
    Layzerbones privados () {} 
    Layzerbones estáticos públicos getInstance () { 
        return layzer; 
    } 
}

1.2 Hambriento

  El modo singleton hambriento se instancia cuando se llama por primera vez;

Badmash de clase pública { 
    Badmash estático privado badmash; 
    Badmash privado () {} 
    Badmash público estático sincronizado getInstance () {// 方法 一
        if (badmash == null) { 
            badmash = new Badmash (); 
        } 
        return badmash; 
    } 
    public static Badmash getInstance2 () {// 方法 二
        if (badmash == null) { 
            sincronizado (Badmash.class) { 
                if (badmash == null) { 
                    badmash = new Badmash (); 
                } 
            } 
        } 
        return badmash; 
    } 
}

Lo que los dos modelos singleton anteriores tienen en común :

1. La clase actual se usa como una variable miembro estática; 2. El constructor se privatiza; 3. Se proporciona un método de instanciación accesible y estático;

La diferencia es:

1. Estilo perezoso: seguridad del hilo;

2. El estilo Han hambriento, el hilo no es seguro, por lo que debemos aumentar el bloqueo;

3. Hay dos maneras de bloquear el estilo chino con hambre: una es agregar un bloqueo al método, la cerradura es un archivo de código de bytes de la clase, la otra es el bloque de código de sincronización y el bloqueo se puede personalizar

4. El propósito de la doble verificación de los bloques de código de sincronización es mejorar la eficiencia de la ejecución;

2. El problema y la optimización del bloqueo de doble verificación chino hambriento

       El problema es que el compilador puede reordenar el código lógico existente durante la compilación;

  

 

Este es un dibujo en "JAVA Concurrent Programming Art", que ilustra claramente el problema, como se muestra a continuación;

 

 

 

El orden de inicialización de los objetos normales es: 1. Primero asigne espacio de memoria al objeto; 2. Inicialice el objeto; 3. Apunte la instancia inicializada a la dirección de memoria asignada.

Pero el problema es que debido a que la reordenación interna de JMM, la inicialización de objetos y los puntos de dirección de instancia a la dirección de memoria pueden reordenarse;

Luego habrá problemas: antes de que el objeto se haya inicializado, ya ha apuntado a la dirección de memoria, y el objeto es nulo; cuando otro hilo accede nuevamente, juzgará nuevamente, será nulo y reinicializará el objeto.

 

 Por supuesto, para este tipo de problema, es mejor resolverlo. Agregue un modificador volátil al miembro estático . Este es un bloqueo liviano para hacer que la variable modificada sea atómica ;

    Badmash estático volátil privado badmash;

Por supuesto, hay otras formas de evitar este problema.

3. Modelo de diseño de singleton interno estático

      Para evitar el problema anterior de inicialización y reorganización de objetos, puede usar el principio de bloqueo de clase en el proceso de inicialización para implementar singletons a través de clases internas;

public class Singleton { 
    private Singleton () { 
    } 
      public static Singleton getInstance () {   
        return Inner.instance;  
    }   
    Private static class Inner {   
        private static final Singleton instancia = new Singleton ();  
    }   
}

4. Enumerar el patrón singleton

     1. Establezca la enumeración de instancias INSTINCT en la enumeración ;

     2. Luego inicialice el objeto que necesita inicializarse en el constructor privado ;

     3. Proporcione métodos externos no estáticos para obtener instancias

enumeración pública SingleEnum {INSTINCT 
;
usuario usuario privado;
SingleEnum () {
usuario = nuevo Usuario ();
}
usuario público getInstance () {
usuario de retorno;
}
}

 

 

¡Lo anterior es el modelo singleton más común!

En este punto, está terminado!

 

Supongo que te gusta

Origin www.cnblogs.com/perferect/p/12760832.html
Recomendado
Clasificación