El patrón singleton es uno de los 23 patrones de diseño. Es un patrón de diseño relativamente simple. Su propósito es devolver el mismo objeto sin importar cuántas veces se llame. Su característica es que el constructor está privatizado.
Está dividido en dos estructuras, una es el estilo del hombre perezoso y la otra es el estilo del hombre hambriento. Cada una tiene sus propias ventajas y desventajas. Comencemos con el estilo del hombre hambriento.
clase pública Único { Único estático privado Único = nuevo Único(); Único privado() { } getInstance público Único() { retorno único;
Se puede ver en el programa anterior que, aunque nuestro propósito de cargar el mismo objeto se ha logrado, el objeto único se creará cuando se cargue el programa. Cuando esta clase tiene varios métodos de este tipo, es posible que no los usemos. en este objeto provocará una pérdida de memoria. Entonces surgió el patrón singleton perezoso. El código es el siguiente:
clase pública Único { Único estático privado = nulo; Único privado () { } getInstance único público () { if(único == nulo) {único = nuevo Único();
De esta manera, el objeto será nuevo solo cuando realmente lo llamemos, pero esto tiene un problema.
Cuando dos subprocesos llaman al segundo fragmento de código anterior cuando se carga por primera vez, se generarán dos objetos diferentes, por lo que no es seguro para subprocesos. En este momento, pensará en agregar un bloqueo, el código después del bloqueo. es el siguiente:
clase pública Single { single estático privado = null; single privado () { } getInstance único sincronizado público () { if (single == null) { single = new Single () return single;
Esto logra la seguridad del hilo, pero cuando el método de bloqueo necesita realizar muchas cosas, llamar a este método llevará mucho tiempo, lo cual es fatal para el servidor, porque si un hilo sigue llamando a este método, no hay forma de ajustarlo. otros subprocesos y el servidor se bloqueará. Entonces el código actualizado es el siguiente:
clase pública Single { priate static Single = null; private Single() { } public Single getInstance() { if (single == null) { sincronizado (Single.class) { single = new Single(); } }
Después de una observación cuidadosa, descubrí que no hay ningún bloqueo de esta manera. Cuando dos subprocesos llegan al método getInstance () por primera vez, uno de ellos debe bloquearse. Después de que el otro complete la ejecución, el subproceso bloqueado se bloqueará. ya no Para determinar si está vacío, aún se creará un objeto. De esta manera, se generarán varios objetos y luego se actualizarán. El código resultante es el siguiente:
clase pública Único { Único estático privado Único = nulo; Único privado () { } getInstance único público () { si (único == nulo) { sincronizado (Único.clase) { si (único == nulo) {único = nuevo Único (); } } } devolver único;
De esta manera, el problema anterior no ocurrirá y solo se bloqueará una vez, porque cuando el método se ejecute por segunda vez, se omitirá el juicio if y el single se devolverá directamente. No se volverá a bloquear. , y la eficiencia de ejecución será muy alta.
Pero aun así, todavía hay un problema, porque no podemos estar seguros de si al objeto se le asigna un valor en la memoria primero o si el objeto se crea primero, por lo que el segundo programa puede obtener un objeto medio inicializado en jdk1. , podemos usar la palabra clave volátil para evitar esta situación. El código es el siguiente:
clase pública Única {privada estática volátil Única única = nula privada Única() { } pública Única getInstance() { if (única == nula) { sincronizada (Única.clase) { si (única == nula) { única = nueva Sencillo(); } } } devolver único;
Pero esta situación rara vez se usa, solo estoy aquí para aprender, jeje.