¿El patrón singleton es solo perezoso y hambriento? Después de leer este artículo, obtendrá puntos extra para su entrevista.

prefacio

Cuando se trata de patrones de diseño, el patrón singleton es el más probable que ocupe el primer lugar en la entrevista. Este debe ser el conocimiento básico que la mayoría de las personas no pueden evitar al comenzar a entrevistar.

Pero el modo singleton no solo tiene dos métodos de escritura: el modo de hombre perezoso y el modo de hombre hambriento, sino que a menudo lo que hemos dominado es la forma de escritura más básica.Si ha leído el código fuente de marcos conocidos como Spring, definitivamente encontrarás su modo singleton Lo que tienes es completamente diferente.

Este artículo le brindará el método de escritura del modo singleton desde básico -> óptimo -> recomendación adicional, para ayudarlo a agregar puntos locos a la entrevista.


hombre perezoso hambriento

1. Modo hombre hambriento

La comprensión simple del modo de hombre hambriento es que el objeto ha sido creado de antemano.

Ventajas: escritura simple, sin problemas de sincronización de subprocesos

Desventaja: debido a que el objeto debe crearse con anticipación, siempre ocupará memoria, independientemente de si se usa o no.

Recomendación: use el modo Hungry Man si el objeto es pequeño y simple

public final class Singleton {
    
     
    // 创建好实例 
    private static Singleton instance = new Singleton();
    // 构造函数 
    private Singleton() {
    
    } 
    // 获取实例 
    public static Singleton getInstance() {
    
    
        return instance; 
    } 
}

2. Modo perezoso

La comprensión simple del modo de hombre perezoso es crear objetos solo cuando sea necesario

Ventajas: el método de carga diferida tiene un mayor rendimiento

Desventajas: considere problemas de sincronización de subprocesos múltiples

Recomendación: siempre que no cumpla con las condiciones de uso recomendadas para el hombre hambriento anterior, use el modo de hombre perezoso

public final class Singleton {
    
     
    private static Singleton instance = null;
    // 构造函数 
    private Singleton() {
    
    } 
    // 获取实例
    public static Singleton getInstance() {
    
    
        // 为null时才实例化对象
        if (null == instance) {
    
    
            instance = new Singleton();
        } 
        return instance;
    } 
}

bloqueo de sincronización

La desventaja del hombre perezoso presentado anteriormente es el problema de la sincronización de subprocesos múltiples, por lo que puede pensar de inmediato en usar bloqueos de sincronización para resolver este problema.

La palabra clave sincronizada se usa aquí y la granularidad de bloqueo se reduce a través de bloques de código, lo que garantiza la sobrecarga de rendimiento en la mayor medida. De hecho, desde java8, el rendimiento de sincronizado ha mejorado mucho.

public final class Singleton {
    
     
    private static Singleton instance = null;
    // 构造函数 
    private Singleton() {
    
    }
    // 获取实例
    public static Singleton getInstance() {
    
    
        // 获取对象时加上同步锁
        if (null == instance) {
    
    
            synchronized (Singleton.class) {
    
     
                instance = new Singleton();
            } 
        } 
        return instance;
    } 
}

bloqueo de doble control

Aunque el bloque de código de bloqueo de sincronización se usa anteriormente, el problema de la sincronización de subprocesos apenas se resuelve y la sobrecarga de rendimiento se optimiza al máximo, pero de hecho todavía hay problemas de seguridad de subprocesos en un entorno de subprocesos múltiples.

Cuando todavía hay múltiples subprocesos ingresando al juicio if, este problema de seguridad de subprocesos aún existe.Aunque esta situación no necesariamente ocurre, la probabilidad de que ocurra en casos extremos es muy alta.

En este momento, debe usar el DCL que le gusta preguntar sobre el patrón de diseño en la entrevista, es decir, el modo de bloqueo de verificación doble. Suena muy sofisticado, pero en realidad es una capa adicional de juicio.

Para decirlo sin rodeos, se verifica antes y después de ingresar al bloqueo de sincronización, lo que reduce en gran medida el problema de seguridad de subprocesos.

public final class Singleton {
    
     
    private static Singleton instance = null;
    // 构造函数 
    private Singleton() {
    
    } 
    // 获取实例
    public static Singleton getInstance() {
    
    
        // 第一次判断,当instance为null时则实例化对象
        if(null == instance) {
    
    
            synchronized (Singleton.class) {
    
    
                // 第二次判断,放在同步锁中,当instance为null时则实例化对象 
                if(null == instance) {
    
    
                    instance = new Singleton();
                } 
            } 
        } 
        return instance;
    } 
}

bloqueo óptimo de doble control

El método de bloqueo de doble verificación es una de las mejores soluciones para el modo de hombre perezoso único para tratar los problemas de seguridad en subprocesos múltiples, pero lo anterior aún no es la mejor manera de escribir.

Aquí hay un concepto de "reordenamiento de instrucciones". Este concepto está en el modelo de memoria Java. Aquí te ayudaré a entenderlo de la manera más concisa.

En Java, la secuencia normal de ejecución de instrucciones para un nuevo objeto en la memoria es: asignación -> creación -> referencia, mientras que en un entorno de subprocesos múltiples, JVM puede reorganizar el orden para la optimización de las declaraciones: asignación -> referencia -> creación .

Si esto sucede, el método de bloqueo de doble verificación anterior aún no puede resolver el problema de seguridad del subproceso.

La solución es muy simple, solo agregue una palabra clave volátil.

El papel de la palabra clave volátil: asegurar la visibilidad y el orden.

public final class Singleton {
    
     
    // 加上volatile关键字
    private volatile static Singleton instance = null;
    // 构造函数 
    private Singleton() {
    
    } 
    // 获取实例
    public static Singleton getInstance() {
    
    
        // 第一次判断,当instance为null时则实例化对象
        if(null == instance) {
    
    
            synchronized (Singleton.class) {
    
    
                // 第二次判断,放在同步锁中,当instance为null时则实例化对象 
                if(null == instance) {
    
    
                    instance = new Singleton();
                } 
            } 
        } 
        return instance;
    } 
}

modo de enumeración

"Effective Java" es un libro muy popular en la industria de Java. Para los programadores que quieren cultivarse en el campo de Java, no hay razón para no leer este libro. Creo que muchos programadores de Java lo han leído o no. Todos han escuchado de este libro

El autor de este libro recomienda un patrón de diseño singleton, que es el método de enumeración.

El principio es muy simple: en Java, el dominio de la clase de enumeración se declarará como un atributo estático después de la compilación, y la JVM se asegurará de que la variable miembro modificada estática solo se instancia una vez.

public class Singleton {
    
    

   // 构造函数
   private Singleton() {
    
    
   }

   // 从枚举中获取实例
   public static Singleton getInstance() {
    
    
      return SingletonEnum.SINGLETON.getInstance();
   }

   // 定义枚举
   private enum SingletonEnum {
    
    
      SINGLETON;

      private Singleton instance;

      // JVM保证这个方法只调用一次
      SingletonEnum() {
    
    
         instance = new Singleton();
      }

      public Singleton getInstance() {
    
    
         return instance;
      }
   }
}

Resumir

Finalmente, aquí hay una pequeña mención, para que algunas personas no se sientan un poco agobiadas por los patrones de diseño.

El modo singleton es realmente muy simple. El modo de hombre hambriento y el modo de hombre perezoso se usan ampliamente en muchos marcos de código abierto, e incluso el modo de hombre hambriento se usa más. Por ejemplo, esto se hace en la clase Runtime de Java. es simple y grosero Si está interesado, puede mirar el código fuente usted mismo.

¿No se dan cuenta los autores de estos marcos de los problemas descritos en este artículo? No, la forma de escribir el patrón singleton a menudo depende de la situación. Algunos problemas que ocurrirán en teoría a menudo son insignificantes en la práctica. En este momento Más inclinado a utilizar la forma de escritura más sencilla y directa.

Lo realmente difícil es en realidad la entrevista. Muchas preguntas sobre el modo singleton les gusta preguntar sobre sus diversas formas de escritura, los problemas existentes y la mejor solución. El grado de comprensión de los patrones de diseño, para juzgar su actitud y logros en la investigación. este tema.

Por lo tanto, después de leer este artículo, puede intentar escribirlo manualmente, es suficiente saber algo y no es necesario profundizar demasiado, porque de hecho hay demasiados lugares que requieren energía en el campo de Java.


experiencia

Finalmente, permítanme hablar sobre mi experiencia. El llamado patrón de diseño ciertamente puede aportar más elegancia al código Java en sí mismo, pero después de escribir código Java durante muchos años, sigo pensando que Java en sí mismo tiene demasiadas decoraciones, y el código es a menudo intercambiado por elegancia propia carga.

En los equipos de I+D en los que he participado, casi puedo ver códigos más elegantes escritos por muchos ingenieros, y algunos patrones de diseño también están bien escritos, pero los problemas que pueden causar también son obvios, es decir, la legibilidad está empeorando y cada miembro del equipo tiene un alto rendimiento en Java, e incluso ejerce presión sobre los recursos humanos en ciertos momentos, lo cual es inapropiado desde un punto de vista práctico.

Mi sugerencia más es que es beneficioso comprender el patrón de diseño frente a la entrevista o el estudio, pero en el trabajo real, trate de usar patrones de diseño menos complejos y concéntrese en un código conciso y directo, lo que conduce al mantenimiento posterior de todo el equipo Incluso acelera la adaptabilidad de los nuevos miembros al proyecto después de los cambios de personal, porque el trabajo aún está orientado al rendimiento, y puede hacer lo que sea simple y eficiente, y puede jugar sus propios proyectos personales como lo desee .



Mi artículo original está escrito puramente a mano, si crees que hay un poco de ayuda, por favor dale me gusta y márcalo como favorito ~

He estado compartiendo mis conocimientos, experiencia y casos prácticos en mi trabajo durante mucho tiempo. Si te gusta, también puedes ir a mi página de inicio personal para prestar atención ~

Supongo que te gusta

Origin blog.csdn.net/xiangyangsanren/article/details/126689540
Recomendado
Clasificación