Concept:
The single case pattern in Java is a common design pattern, the single example mode is divided into three kinds: the lazy type single case, the A Hungry man type single case, the registration type single example three kinds.
A single case pattern has some features:
1, Singleton class can only have one instance.
2. A singleton class must create its own unique instance.
3. A singleton class must provide this instance to all other objects.
The singleton pattern ensures that a class has only one instance and instantiates it itself and supplies the instance to the entire system. In computer systems, the driver objects of thread pools, caches, log objects, dialog boxes, printers, and graphics cards are often designed as single examples. These applications have more or less the functionality of the resource manager. Each computer can have several printers, but only one printer Spooler to prevent two print jobs from being exported to the printer at the same time. Each computer can have several communication ports, and the system should centrally manage these communication ports to avoid a single communication port being invoked simultaneously by two requests. In short, the choice of single case mode is to avoid inconsistent state, to avoid the administration of the Bulls.
Here are two main details: lazy type and a hungry man style
First, immediately loaded/a hungry man type
Before the method is invoked, the instance is created, and the code:
Package com.weishiyao.learn.day8.singleton.ep1;
public class MyObject {
//immediate load mode = = Evil Han mode
private static MyObject MyObject = new MyObject ()
; Private MyObject () {
} public
static MyObject getinstance () {
//This code version for immediate loading
////This version of the code has the disadvantage that there cannot be other instance variables
//Because the getinstance () method is not synchronized
//So it is possible to have a thread-safe problem return
MyObject
}
}
Creating a Thread class
Package com.weishiyao.learn.day8.singleton.ep1;
public class Mythread extends Thread {
@Override public
void Run () {
System.out.println ( Myobject.getinstance (). Hashcode ());
}
To create a running class
Package com.weishiyao.learn.day8.singleton.ep1;
public class Run {public
static void Main (string[] args) {
mythread t1 = new Mythread ();
Mythread t2 = new Mythread ();
mythread t3 = new Mythread ();
T1.start ();
T2.start ();
T3.start ();
}
Run results
167772895
167772895
167772895
Hashcode is the same value, indicating that the object is also the same, which shows that the simple mode is implemented immediately loaded
Second, delayed loading/lazy type
The instance is created after the method is called, and the implementation can put the instantiation into an parameterless constructor so that an instance of the object is created only when the call is made, and the code:
Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;
public class MyObject {
private static MyObject MyObject;
Private MyObject () {
} public
static MyObject getinstance () {
//deferred load
if (MyObject!= null) {
} else {
myObject = new MyObject ();
}
Return MyObject
}
}
Creating a Thread class
Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;
public class Mythread extends Thread {
@Override public
void Run () {
System.out.println ( Myobject.getinstance (). Hashcode ());
}
To create a running class
Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;
public class Run {public
static void Main (string[] args) {
mythread t1 = new Mythread ();
T1.start ();
}
Run results
167772895
This way, although an instance of an object is taken out, if multiple instances are present in a multithreaded environment, this is not a singleton pattern.
Run the test class
Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP2;
public class Run {public
static void Main (string[] args) {
mythread t1 = new Mythread ();
Mythread t2 = new Mythread ();
mythread t3 = new Mythread ();
mythread T4 = new Mythread ();
Mythread T5 = new Mythread ();
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
}
Run results
980258163
1224717057
1851889404
188820504
1672864109
Since there is a problem, it is necessary to solve the problem in the lazy mode of multithreaded solution, code:
The first scheme, the most common, adds synchronized, and synchronized can be added to different locations
The first method of locking
Package com.weishiyao.learn.day8.singleton.ep3;
public class MyObject {
private static MyObject MyObject;
Private MyObject () {
}
synchronized public static MyObject getinstance () {
//lazy load
try {
if ( MyObject!= null) {
} else {
//simulate doing some preparatory work before creating the object
Thread.Sleep (watts);
MyObject = new MyObject ();
}
} catch (Interruptedexception e) {
e.printstacktrace ();
}
Return MyObject
}
}
This synchronized synchronization scheme leads to inefficiencies, and the entire approach is locked.
The second type of synchronized use scheme
Package com.weishiyao.learn.day8.singleton.ep3;
public class MyObject {
private static MyObject MyObject;
Private MyObject () {
} public
static MyObject getinstance () {
//lazy load
try {
synchronized ( Myobject.class) {
if (MyObject!= null) {
} else {
//simulate doing some preparatory work before creating the object
Thread.Sleep (watts);
MyObject = new MyObject ();}}
catch (Interruptedexception e) {
e.printstacktrace ();
}
Return MyObject
}
}
This approach is as inefficient as all the code within the method is locked, just to lock in the key code, and the third synchronized use scenario
Package com.weishiyao.learn.day8.singleton.ep3;
public class MyObject {
private static MyObject MyObject;
Private MyObject () {
} public
static MyObject getinstance () {
//deferred load
try {
if (MyObject!= null) {
} else {
//simulate doing some preparatory work before creating an object
Thread.Sleep;
Synchronized (myobject.class) {
MyObject = new MyObject ();
}
catch (interruptedexception e) { C16/>e.printstacktrace ();
}
Return MyObject
}
}
So it seems like the best solution, but, run the results, found that it is not thread-safe
Results:
1224717057
971173439
1851889404
1224717057
1672864109
Why?
Although the statement created by the object is locked, only one thread can complete the creation at a time, but when the first thread comes in to create the completion object, the second thread comes in and can continue to be created, because we lock the creation statement tightly, and the problem solution
Package com.weishiyao.learn.day8.singleton.ep3;
public class MyObject {
private static MyObject MyObject;
Private MyObject () {
} public
static MyObject getinstance () {
//deferred load
try {
if (MyObject!= null) {
} else {
//simulate doing some preparatory work before creating an object
Thread.Sleep;
Synchronized (myobject.class) {
if (MyObject = null) {
MyObject = new MyObject ();
}
}}
catch (Interruptedexception e) {
e.printstacktrace ();
}
Return MyObject
}
}
Only need to add a judge in the lock, you can guarantee a single case, this is DCL double check mechanism
The results are as follows:
1224717057
1224717057
1224717057
1224717057
1224717057
third, the use of built-in static class implementation of a single case
Main code
Package com.weishiyao.learn.day8.singleton.ep4;
public class MyObject {
//inner class way
private static class Myobjecthandler {
private static MyObject MyObject = new MyObject ();
}
Public MyObject () {
} public
static MyObject getinstance () {return
myobjecthandler.myobject;
}
}
Thread Class Code
Package com.weishiyao.learn.day8.singleton.ep4;
public class Mythread extends Thread {
@Override public
void Run () {
System.out.println ( Myobject.getinstance (). Hashcode ());
}
Run class
Package com.weishiyao.learn.day8.singleton.ep4;
public class Run {public
static void Main (string[] args) {
mythread t1 = new Mythread ();
Mythread t2 = new Mythread ();
mythread t3 = new Mythread ();
mythread T4 = new Mythread ();
Mythread T5 = new Mythread ();
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
}
Results
1851889404
1851889404
1851889404
1851889404
1851889404
A single case pattern of thread safety is obtained through the internal static class
Iv. serialization and deserialization of single case patterns
Built-in static classes can achieve thread-safe problems, but if you encounter a serialized object, the result of using the default method is more or more
MyObject Code
Package com.weishiyao.learn.day8.singleton.ep5;
Import java.io.Serializable;
public class MyObject implements Serializable {
/**
* */
private static final long Serialversionuid = 888 L;
Internal class way
private static class Myobjecthandler {
private static MyObject MyObject = new MyObject ();
}
Public MyObject () {
} public
static MyObject getinstance () {return
myobjecthandler.myobject;
} protected MyObject readresolve () {
// System.out.println () called Readresolve Method! ");
return Myobjecthandler.myobject;
// }
}
Business class
Package com.weishiyao.learn.day8.singleton.ep5;
Import Java.io.File;
Import Java.io.FileInputStream;
Import java.io.FileNotFoundException;
Import Java.io.FileOutputStream;
Import java.io.IOException;
Import Java.io.ObjectInputStream;
Import Java.io.ObjectOutputStream; public class Saveandread {public static void main (string[] args) {try {MyObject MyObject = Myobject.getinst
Ance ();
FileOutputStream fosref = new FileOutputStream (New File ("MyObjectFile.txt"));
ObjectOutputStream oosref = new ObjectOutputStream (FOSREF);
Oosref.writeobject (MyObject);
Oosref.close ();
Fosref.close ();
System.out.println (Myobject.hashcode ());
catch (FileNotFoundException e) {e.printstacktrace ();
catch (IOException e) {e.printstacktrace ();
} FileInputStream Fisref;
try {fisref = new FileInputStream (New File ("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 (IOException e) {e.printstacktrace ();
catch (ClassNotFoundException e) {e.printstacktrace ();
}
}
}
Results
970928725
1099149023
Two different hashcode, proving not the same object, solution, add the following code
Protected MyObject Readresolve () {
System.out.println () called the Readresolve Method! ");
return myobjecthandler.myobject;
}
Called at the time of deserialization, you can get the same object
System.out.println (Myobject.readresolve (). Hashcode ());
Results
1255301379
Called the Readresolve Method!
1255301379
Same hashcode, proved to have got the same object
The use of static code block implementation of a single case
The code in the static code block is executed when the class is used, so it is possible to apply the static code fast feature to implement the simple pattern.
MyObject class
Package com.weishiyao.learn.day8.singleton.ep6;
public class MyObject {
private static MyObject instance = null;
Private MyObject () {
super ();
}
static {
instance = new MyObject ();
}
public static MyObject getinstance () {return
instance;
}
}
Thread class
Package com.weishiyao.learn.day8.singleton.ep6;
public class Mythread extends Thread {
@Override public
void Run () {for
(int i = 0; i < 5; i++) {
System.out.println (Myobject.getinstance (). Hashcode ());}}}
Run class
Package com.weishiyao.learn.day8.singleton.ep6;
public class Run {public
static void Main (string[] args) {
mythread t1 = new Mythread ();
Mythread t2 = new Mythread ();
mythread t3 = new Mythread ();
mythread T4 = new Mythread ();
Mythread T5 = new Mythread ();
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
}
Run Result:
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
1678885403
A single case pattern of thread safety is also successfully obtained by performing only one feature of the static code block
Vi. enumerating data types using enum to implement a single case pattern
enumeration enum and static code block features are similar, when using enumerations, the constructor is invoked automatically, or it can be used to implement a single case pattern
MyObject class
Package com.weishiyao.learn.day8.singleton.ep7;
Import java.sql.Connection;
Import Java.sql.DriverManager;
Import java.sql.SQLException;
public enum MyObject {
connectionfactory;
Private Connection Connection;
Private MyObject () {
try {
System.out.println ("Call MyObject construct");
String url = "Jdbc:mysql://172.16.221.19:3306/wechat_1?useunicode=true&characterencoding=utf-8";
String name = "root";
String password = "111111";
String drivername = "Com.mysql.jdbc.Driver";
Class.forName (drivername);
Connection = drivermanager.getconnection (URL, name, password);
} catch (ClassNotFoundException e) {
e.printstacktrace ();
} catch (SQLException e) {
e.printstacktrace () ;
}
}
Public Connection getconnection () {return
Connection;
}
}
Thread class
Package com.weishiyao.learn.day8.singleton.ep7;
public class Mythread extends Thread {
@Override public
void Run () {for
(int i = 0; i < 5; i++) {
Syst Em.out.println (MyObject.connectionFactory.getConnection (). Hashcode ());}}}
Run class
Package com.weishiyao.learn.day8.singleton.ep7;
public class Run {public
static void Main (string[] args) {
mythread t1 = new Mythread ();
Mythread t2 = new Mythread ();
mythread t3 = new Mythread ();
mythread T4 = new Mythread ();
Mythread T5 = new Mythread ();
T1.start ();
T2.start ();
T3.start ();
T4.start ();
T5.start ();
}
Run results
Called the construction of the MyObject
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
56823666
This type of writing exposes the enumeration class, violates the "principle of responsibility", and wraps the enumeration with a single class
Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP8;
Import java.sql.Connection;
Import Java.sql.DriverManager;
Import java.sql.SQLException;
public class MyObject {public enum Myenumsingleton {connectionfactory;
Private Connection Connection;
Private Myenumsingleton () {try {System.out.println ("call MyObject construct");
String url = "Jdbc:mysql://172.16.221.19:3306/wechat_1?useunicode=true&characterencoding=utf-8";
String name = "Root";
String password = "111111";
String drivername = "Com.mysql.jdbc.Driver";
Class.forName (drivername);
Connection = drivermanager.getconnection (URL, name, password);
catch (ClassNotFoundException e) {e.printstacktrace ();
catch (SQLException e) {e.printstacktrace ();
} public Connection getconnection () {return Connection; } public static Connection getconnection () {return Myenumsingleton.conneCtionfactory.getconnection ();
}
}
Changing the thread code
Package COM.WEISHIYAO.LEARN.DAY8.SINGLETON.EP8;
public class Mythread extends Thread {
@Override public
void Run () {for
(int i = 0; i < 5; i++) {
Syst Em.out.println (Myobject.getconnection (). Hashcode ());}}}
Results
Called the construction of the MyObject
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
1948356121
The above summarizes the various situations and solutions that are encountered when the simple mode is combined with multithreading for later use.