concepto:
El patrón Singleton en Java es un patrón de diseño común. Singleton Pattern se divide en tres tipos: Singleton Lazy, Hungry Singleton y Singleton registrado.
El modo singleton tiene las siguientes características:
1. Solo puede haber una instancia en una clase Singleton.
2. La clase Singleton debe crear su propia instancia única.
3. La clase Singleton debe proporcionar esta instancia a todos los demás objetos.
Singleton Pattern asegura que una clase tenga solo una instancia, y la instancia misma y proporciona esta instancia a todo el sistema. En los sistemas informáticos, los objetos del controlador para grupos de roscas, cachés, objetos de registro, cuadros de diálogo, impresoras y tarjetas gráficas a menudo se diseñan como solteros. Estas aplicaciones tienen más o menos la funcionalidad de un administrador de recursos. Cada computadora puede tener varias impresoras, pero solo puede estar disponible una bobina de impresora para evitar que se emitan dos trabajos de impresión a la impresora al mismo tiempo. Cada computadora puede tener varios puertos de comunicación, y el sistema debe administrar centralmente estos puertos de comunicación para evitar que un puerto de comunicación se llame simultáneamente por dos solicitudes. En resumen, elegir un modelo singleton es evitar estados inconsistentes y evitar el optimismo político.
Aquí hay dos tipos de presentaciones: perezoso y hambriento
1. Cargar inmediatamente/estilo hambriento
Antes de llamar al método, se ha creado la instancia, código:
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {// carging ahora == Modo malvado Private static myObject myObject = new myObject (); private myObject () {} public static myObject getInstance () {// Esta versión de código está cargando ahora // la desatinta de esta versión de la variedad de código que no puede haber otro código que no esté allí. El método getInStance () no está sincronizado // por lo tanto, los problemas no seguros pueden ocurrir myObject;}} Crear una clase de hilo
paquete com.weishiyao.learn.day.singleton.ep; public class myThread extiende el hilo {@OverridePublic void run () {System.out.println (myObject.getInstance (). HashCode ());}} Crea una clase de ejecución
paquete com.weishiyao.learn.day.singleton.ep; public class run {public static void main (string [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); t.start (); t.start (); t.start (); t.start ();}} Resultados de ejecución
1 167772895
2 167772895
3 167772895
Hashcode es el mismo valor, lo que significa que el objeto también es el mismo, lo que significa que se implementa el modo de carga instantánea.
2. Carga perezosa/perezoso
La instancia se creará después de que se llame al método. El plan de implementación puede ser poner instanciación en el constructor sin parámetros, de modo que se cree una instancia del objeto solo cuando se llame al método. Código:
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInStance () {// retraso de carga if (myObject! = null) {} else {myObject = new myObject ();} return myObject;}}}} Crear una clase de hilo
paquete com.weishiyao.learn.day.singleton.ep; public class myThread extiende el hilo {@OverridePublic void run () {System.out.println (myObject.getInstance (). HashCode ());}} Crea una clase de ejecución
paquete com.weishiyao.learn.day8.singleton.ep2; public class run {public static void main (string [] args) {mythread t1 = new myThread (); t1.start ();}} Resultados de ejecución
1 167772895
Aunque se toma una instancia de un objeto, si se encuentra en un entorno múltiple, se producirán múltiples instancias, lo que no es un patrón singleton
Ejecutar la clase de prueba
paquete com.weishiyao.learn.day.singleton.ep; public class run {public static void main (string [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new new Mythread (); t.start (); t.start (); t.start (); t.start (); t.Start (); t.Start (); }} Resultados de ejecución
1 980258163
2 1224717057
3 1851889404
4 188820504
5 1672864109
Como hay un problema, necesitamos resolver el problema. Solución múltiple en modo perezoso, código:
La primera solución, más comúnmente, se sincronizada y sincronizada se puede agregar a diferentes posiciones
El primer método bloquea
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} sincronizado public static myObject getInStance () {// retrasar cargar try {if (myObject! = null) {} else {// simula alguna preparación antes de crear un hilo de objeto () myObject = new MyObject (); }} capt (interruptedException e) {E.PrintStackTrace ();} return myObject;}} Este esquema de sincronización sincronizado da como resultado demasiado ineficiente y todo el método está bloqueado
El segundo esquema de uso sincronizado
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static static myObject getInstance () {// retrasar cargando intento {sincronizado (myObject.classsssss) {if (myObject! Thread.sleep (); myObject = new MyObject ();}}} Catch (InterruptedException e) {E.PrintStackTrace ();} return myObject;}} Este método también es de muy baja eficiencia. Todos los códigos en el método están bloqueados. Solo necesita bloquear el código de llave. El tercer plan de uso sincronizado
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// retraso de carga intente {if (myObject! = null) {} else {// simula algo de preparación antes de crear un objeto hilt.sle drease (); {myObject = new MyObject ();}}} Catch (InterruptedException e) {E.PrintStackTrace ();} return myObject;}} Esta parece ser la mejor solución, pero después de ejecutarla, descubrí que en realidad no es seguro
resultado:
1 1224717057
2 971173439
3 1851889404
4 1224717057
5 1672864109
¿Por qué?
Aunque la declaración que crea un objeto está bloqueada, solo un hilo puede completar la creación a la vez, después de que llega el primer hilo para crear el objeto objeto, el segundo hilo aún puede continuar creando, porque solo bloqueamos la declaración de creación, esta solución de problema
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject myObject; private myObject () {} public static myObject getInstance () {// retrasar cargando try {if (myObject! = null) {} else {// simula algo de preparación antes de crear un objeto hilvado. (MyObject.class) {if (myObject == null) {myObject = new MyObject ();}}}} Catch (InterruptedException e) {E.PrintStackTRace ();} return myObject;}} Simplemente agregue otro juicio a la cerradura para garantizar un singleton. Este es el mecanismo de doble verificación DCL
Los resultados son los siguientes:
1 1224717057
2 1224717057
3 1224717057
4 1224717057
5 1224717057
3. Use clases estáticas incorporadas para implementar casos individuales
Código principal
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {// Método de clase interior clase privada estática MyObjEctHandler {private estático está myobject myObject = new myObject ();} public myObject () {} public static myObject getInstance () {return myObjecthandler.myObject;} Código de clase de hilo
paquete com.weishiyao.learn.day.singleton.ep; public class myThread extiende el hilo {@OverridePublic void run () {System.out.println (myObject.getInstance (). HashCode ());}} Clase de ejecución
paquete com.weishiyao.learn.day.singleton.ep; public class run {public static void main (string [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new new Mythread (); t.start (); t.start (); t.start (); t.start (); t.Start (); t.Start (); }} resultado
1851889404
1851889404
1851889404
1851889404
1851889404
A través de clases estáticas internas, se obtiene un patrón singleton seguro
IV. Serializar y deserializar patrones de singleton
Las clases estáticas incorporadas pueden lograr problemas de seguridad de los subprocesos, pero si encuentra objetos serializados, el resultado obtenido utilizando el método predeterminado sigue siendo múltiples casos.
Código MyObject
paquete com.weishiyao.learn.day8.singleton.ep5; import java.io.Serializable; public class myObject implementa serializable {/****/private static final long serialversionUid = 888l; // Método de clase interna MyobjEctthandler {MyObject myobject myObject MyObject estatoso privado (); {} public static static myObject getInStance () {return myobjEctHandler.myObject;} // myobject protegido readResolve () {// system.out.println ("El método readResolve se llamó!"); // return myobjecthandler.myobject; //}}} Negocio
paquete com.weishiyao.learn.day.singleton.ep; import java.io.file; import java.io.fileInputStream; import java.io.filenotfoundException; import java.io.fileOutputStream; import java.io.ioexception; import java.io.ObjectStream; importar JavautStream; SaveAndread {public static void main (string [] args) {try {myObject myObject = myObject.getInstance (); fileOutputStream fosref = new FileOutputStream (nuevo archivo ("myObjectFile.txt")); ObjectOutputStream oosRef = new New ObjectOutputStream (fosref); oosref.writeObject (myObject); oosref.close (); fosref.close (); system.out.println (myObject.hashcode ());} catch (FileNotFoundException e) {E.PrintStackTrace ();} Catch (IOEXCECEPCION E) {E.PrintStackTrace ();} fileInputStream fisref; try {fisRef = new FileInputStream (nuevo archivo ("myObjectFile.txt")); ObjectInputStream iOSRef = new ObjectInputStream (fisref); myObject myObject = (myObject) iosref.ReadObject (); iosref.close (); fisref.close (); system.out.println (myObject.hashCode ());} catch (fileNotFoundException e) {E.PrintStackTrace ();} Catch (IOOException e) {e.PrintTackTrace ();} {E.PrintStackTrace ();}}} resultado
1 970928725
2 1099149023
Dos hashcodes diferentes demuestran que no son el mismo objeto. Solución, agregue el siguiente código
MyObject protegido readResolve () {System.out.println ("El método readresolve se llamó!"); return myobjecthandler.myobject;} Llamado durante la deserialización, puede obtener el mismo objeto
System.out.println (myObject.readResolve (). HashCode ());
resultado
1 1255301379
2 Se llamó al método Readresolve!
3 1255301379
El mismo húsico demuestra que se obtiene el mismo objeto
5. Use bloques de código estático para implementar un caso único
El código en el bloque de código estático ya se ejecuta cuando se usa la clase, por lo que la característica del código estático se puede usar para implementar el modo de beneficio simple.
Clase myobject
paquete com.weishiyao.learn.day.singleton.ep; public class myObject {private static myObject instance = null; private myObject () {super ();} static {instance = new myObject ();} public static static myObject getInstance () {return instancia;}} Clase de hilo
paquete com.weishiyao.learn.day.singleton.ep; public class myThread extiende el hilo {@OverridePublic Void run () {for (int i =; i <; i ++) {System.out.println (myObject.getInstance (). Hashcode ());}}} Clase de ejecución
paquete com.weishiyao.learn.day.singleton.ep; public class run {public static void main (string [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new new Mythread (); t.start (); t.start (); t.start (); t.start (); t.Start (); t.Start (); }} Resultados de ejecución:
1 1678885403
2 1678885403
3 1678885403
4 1678885403
5 1678885403
6 1678885403
7 1678885403
8 1678885403
9 1678885403
10 1678885403
11 1678885403
12 1678885403
13 1678885403
14 1678885403
15 1678885403
16 1678885403
17 1678885403
18 1678885403
19 1678885403
20 1678885403
21 1678885403
22 1678885403
23 1678885403
24 1678885403
25 1678885403
El patrón Singleton seguro a hilo se obtiene con éxito a través de la característica de solo ejecutar bloques de código estático una vez.
6. Use tipos de datos de enum enum para implementar el modo singleton
Las características de Enum enum y bloques de código estático son similares. Al usar enums, el constructor se llamará automáticamente y también se puede usar para implementar el modo singleton.
Clase myobject
paquete com.weishiyao.learn.day.singleton.ep; import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; public enum myObject {ConnectionFactory; private Connection Connection; private MyObject () {intit {system.out.println ("The Connection de MyObject; "jdbc: mysql: // ...:/wechat_? useUnicode = true & caracteresCoding = utf-"; string name = "root"; string contraseña = ""; string drivername = "com.mysql.jdbc.driver"; class.forne (drivername); conexión = drivermanager.getConnection (url, name, contraseña); e) {E.PrintStackTrace ();} Catch (Sqlexception E) {E.PrintStackTrace ();}} Public Connection getConnection () {return Connection;}} Clase de hilo
paquete com.weishiyao.learn.day.singleton.ep; public class myThread extiende hilo {@OverridePublic Void run () {for (int i =; i <; i ++) {System.out.Println (myObject.ConnectionFactory.getConnection (). Hashcode ();}}} Clase de ejecución
paquete com.weishiyao.learn.day.singleton.ep; public class run {public static void main (string [] args) {mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new mythread (); mythread t = new new Mythread (); t.start (); t.start (); t.start (); t.start (); t.Start (); t.Start (); }} Resultados de ejecución
1 Se llamó a la construcción myobject
2 56823666
3 56823666
4 56823666
5 56823666
6 56823666
7 56823666
8 56823666
9 56823666
10 56823666
11 56823666
12 56823666
13 56823666
14 56823666
15 56823666
16 56823666
17 56823666
18 56823666
19 56823666
20 56823666
21 56823666
22 56823666
23 56823666
24 56823666
25 56823666
26 56823666
El método de escritura anterior expone la clase de enumeración, que viola el "principio de responsabilidad única". Puede usar una clase para envolver la enumeración.
paquete com.weishiyao.learn.day.singleton.ep; import java.sql.connection; import java.sql.drivermanager; import java.sql.sqlexception; public class myObject {public enum myenumsingon {Connection Connection; private Connection; private Myenumsingleton () Construct of MyObject se llamó "); String url =" jdbc: mysql: // ...:/weChat_? UseUnicode = true y caracterescoding = utf- "; string name =" root "; string contraseña =" "; string drivername =" com.mysql.jdbc.driver "; class.forname (drivername); conexión = drivergerer contraseña);} catch (ClassNotFoundException e) {E.PrintStackTrace ();} Catch (SqLException e) {E.PrintStackTrace ();}} public conexión getConnection () {return Connection;}} Public Static Connection getConnection () {return MyEnumsingEnton.connection.getConnection ();}}}}}}}}}}}}}}}}}}}}}}}}}}} Cambiar el código de hilo
paquete com.weishiyao.learn.day.singleton.ep; public class myThread extiende hilo {@OverridePublic Void run () {for (int i =; i <; i ++) {System.out.println (myObject.getConnection (). Hashcode ());}}} resultado
1 Se llamó a la construcción myobject
2 1948356121
3 1948356121
4 1948356121
5 1948356121
6 1948356121
7 1948356121
8 1948356121
9 1948356121
10 1948356121
11 1948356121
12 1948356121
13 1948356121
14 1948356121
15 1948356121
16 1948356121
17 1948356121
18 1948356121
19 1948356121
20 1948356121
21 1948356121
22 1948356121
23 1948356121
24 1948356121
25 1948356121
26 1948356121
Lo anterior resume varias situaciones y soluciones encontradas al combinar el modo de interés único con múltiples subprocesos, de modo que se pueda revisar cuando se usa más adelante.