Implementación del modo Singleton (5 tipos)
Comúnmente utilizado:
Estilo hambriento (eficiencia de llamada alta, alta llamada, pero no se puede cargar de manera retrasada)
Estilo perezoso (una eficiencia de llamada segura, baja de hilo, se puede cargar en retraso)
otro:
Tipo de bloqueo de detección doble (debido al modelo interno subyacente de JVM, ocasionalmente habrá problemas y no se construirá y utilizará)
Clase interna estática (alta eficiencia de llamadas seguras de hilo, pero se puede cargar de manera retrasada)
Enumere Singleton (a prueba de subprocesos, alta eficiencia de llamadas, y no se puede cargar en retraso)
El código específico del Singleton de Hungry Man es el siguiente:
paquete com.lcx.mode; /** * * Un singleton de personas hambrientas. Independientemente de si este objeto se usa en el futuro o no, creamos una instancia de este objeto desde el principio. * Cuando es necesario, devolvemos el objeto de instancia creado, por lo que tenemos relativamente hambre, por lo que esto se llama un singleton de personas hambrientas. * @Author QQ1013985957 * */ public class SingletonHanger {private static final Singletonhanger instancia = nuevo singletonhanger (); private singletonhanger () {} public static singletonhanger getInstance () {instancia de retorno; }} /*** Singleton al estilo Han Lazy, cuando se necesita un objeto Singleton, creará el único objeto Singleton, y lo volverá a llamar más tarde, y el objeto Singleton devuelto también es el primer objeto Singleton creado* inicializa el miembro estático a NULL, y lo crea cuando se obtiene un singleton, por lo que se llama Lazy Han-Syle. * @Author QQ1013985957 * */ clase Singletonlazy {private static singletonlazy instancia = null; Private Singletonlazy () {} /*** El singleton implementado por este método no puede usarse en múltiples hilos. Múltiples líneas pueden ingresar el método IF al mismo tiempo, lo que provocará que se generen múltiples objetos singleton. * @return */ public static singletonlazy getInstance1 () {if (instance == null) {instancia = new Singletonlazy (); } instancia de retorno; } /*** Todos pensarán en la sincronización. El método sincrónico puede implementar un singleton múltiple* Sin embargo, este método no es deseable y afecta seriamente el rendimiento. Debido a que el método debe verificarse cada vez que obtenga un singleton, solo puede usar el bloque de código sincronizado para lograr la sincronización. * @return */ public static sincronizado sincronizado singletonlazy getInstance2 () {if (instance == null) {install = new Singletonlazy (); } instancia de retorno; } /*** Use el bloque de código sincronizado para usar el bloque de código sincronizado en el método IF para determinar si existe un singleton, y verificar nuevamente en el bloque de código sincronizado si se ha generado el singleton. * Este es el método de verificación doble en Internet * @return */ public static sincronizado sincronizado singletonlazy getInstance3 () {if (instance == null) {sincronizado (singletonlazy.class) {if (instancia == null) {instancia = nueva singletonlazy (); }}} instancia de retorno; }} /*** Use enumeraciones para implementar el modo singleton, que también es la forma recomendada de usar en la instanciación efectiva de Java* de acuerdo con la situación específica. Para los estudiantes que no están familiarizados con enums, puede consultar la comprensión preliminar de mi clase de enumeración de Java. * Sus beneficios: es más conciso y proporciona un mecanismo de serialización de forma gratuita, evitando absolutamente la instanciación múltiple, incluso frente a la secuencia compleja y los ataques de reflexión. * @Author QQ1013985957 * */ enum SingletEnum {SingletionEnum ("Singleton Enum"); cadena privada Str; privado singletionenum (string str) {this.setstr (str); } public String getStr () {return str; } public void setstr (string str) {this.str = str; }} El patrón de singleton anterior no se prueba. Puede probarlo para determinar si el Ccode del objeto es consistente para determinar si es el mismo objeto.
Los métodos malvados y perezosos no pueden evitar que la reflexión implementa múltiples instancias. A través de la reflexión, establecer el método accesible.setAccessible puede llamar al constructor privado. Puede modificar el constructor para lanzar una excepción cuando se le pide que cree una segunda instancia.
De hecho, esto no puede garantizar un singleton. Después de la serialización, la deserialización puede crear una nueva instancia y agregar el método ReadResolve () a la clase Singleton para evitarlo.
El código singleton de estilo Lazy Man es el siguiente:
paquete com.lcx.mode; import java.io.file; import java.io.fileInputStream; import java.io.fileOutputStream; import java.io.objectInputStream; import java.io.objectOutputStream; import java.io.serializable; import java.lang.reflect.constructor; import java.lang.reflect.invocationTargetException; /*** Se crean singletons de estilo hombre perezoso cuando se necesita un objeto singleton. Cuando se necesita un objeto singleton, se llamará nuevamente más tarde. El objeto singleton devuelto también es el primer objeto Singleton creado* inicializa el miembro estático a NULL, y lo crea cuando se obtiene un singleton, por lo que se llama estilo de hombre perezoso. * @author QQ1013985957 * */ public class Singleton implementa serializable {/ ** * */ private static final long SerialVersionUid = -5271537207137321645l; Instancia privada de Singleton Singleton = NULL; static private int i = 1; private singleton () { / *** Evite ataques de reflexión, solo ejecute y llame al constructor una vez, arroje excepción la segunda vez* / if (i == 1) {i ++; } else {lanzar nueva runtimeException ("El constructor solo se puede llamar una vez"); } System.out.println ("Llame al constructor privado de Singleton"); } /*** Use el bloque de código sincronizado para usar el bloque de código sincronizado en el método IF para determinar si existe un singleton, y verificar nuevamente en el bloque de código sincronizado si se ha generado el singleton. * Esto es lo que Internet llama el método de bloqueo de doble verificación * @return */ public static sincronizado sincronizado getInStance () {if (instance == null) {sincronizado (singleton.class) {if (instance == null) {instancia = nuevo singleton (); }} instancia de retorno; } /*** Evite que la desquio genere nuevos objetos singleton. Esto es lo que se dice en el libro Efective Java. Este método se puede prevenir. No entiendo los detalles específicos * @return */ private Object readResolve () {return instancia; } public static void main (string [] args) lanza la excepción {test1 (); test2 (); } / *** Testing Laquence sigue siendo el modo Singleton* @throws Exception* / public static void test2 () lanza la excepción {Singleton S = Singleton.getInstance (); ObjectOutputStream ObjectOutputStream = nuevo ObjectOutputStream (nuevo FileOutputStream (nuevo archivo ("e: //singleton.txt")); ObjectOutputStream.WriteObject (s); ObjectInputStream ObjectInputStream = new ObjectInputStream (new FileInputStream (nuevo archivo ("e: //singleton.txt"))); Objeto readObject = objectInputStream.ReadObject (); Singleton S1 = (Singleton) ReadObject; System.out.println ("s.hashcode ():"+s.hashcode ()+", s1.hashcode ():"+s1.hashcode ()); ObjectOutputStream.Flush (); ObjectOutputStream.close (); ObjectInputStream.Close (); ObjectInputStream.Close (); } / *** Test Reflection Attack* @throws Exception* / public static void test1 () {singleton s = singleton.getInstance (); Clase C = Singleton.Class; Constructor privateConstructor; intente {privateConstrucor = c.getDeClaredConstructor (); privateConstructor.SetAccessible (verdadero); privateConstructor.newinstance (); } catch (Exception e) {E.PrintStackTrace (); }}}Verifique los resultados del ataque de reflexión:
Si no se agrega el resultado del método ReadResolve:
El resultado de agregar el método ReadResolve:
Gracias por leer, espero que pueda ayudarte. ¡Gracias por su apoyo para este sitio!