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.day.singleton.ep;
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.day.singleton.ep;
public class Mythread extends Thread {
@Override public
void Run () {
System.out.println ( Myobject.getinstance (). Hashcode ());
}
To create a running class
Package 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 ();
}
Run results
1 167772895
2 167772895
3 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.day.singleton.ep;
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.day.singleton.ep;
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
1 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.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 mythread ();
T.start ();
T.start ();
T.start ();
T.start ();
T.start ();
}
Run results
1 980258163
2 1224717057
3 1851889404
4 188820504
5 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.day.singleton.ep;
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 (); myObject = new MyObject ();}
CATC H (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.day.singleton.ep;
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 ();
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.day.singleton.ep;
public class MyObject {
private static MyObject MyObject;
Private MyObject () {
} public
static MyObject getinstance () {
//lazy load
try {
if (MyObject!= null {
} else {
//simulate doing some preparatory work before creating the object
Thread.Sleep ();
Synchronized (myobject.class) {
MyObject = new MyObject ();
}
catch (interruptedexception e) { C39/>e.printstacktrace ();
}
return myObject;
}
So it seems like the best solution, but, run the results, found that it is not thread-safe
Results:
1 1224717057
2 971173439
3 1851889404
4 1224717057
5 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.day.singleton.ep;
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 the 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:
1 1224717057
2 1224717057
3 1224717057
4 1224717057
5 1224717057
Third, the use of built-in static class implementation of a single case
Main code
Package com.weishiyao.learn.day.singleton.ep;
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.day.singleton.ep;
public class Mythread extends Thread {
@Override public
void Run () {
System.out.println ( Myobject.getinstance (). Hashcode ());
}
Run class
Package 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 mythread ();
T.start ();
T.start ();
T.start ();
T.start ();
T.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.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.ObjectInputStream;
Import Java.io.ObjectOutputStream;
public class Saveandread {public static void main (string[] args) {try {MyObject MyObject = myobject.getinstance ();
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 (Classnotf
Oundexception e) {e.printstacktrace ();}} }
Results
1 970928725
2 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
1 1255301379
2 called the Readresolve Method!
3 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.day.singleton.ep;
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.day.singleton.ep;
public class Mythread extends Thread {
@Override public
void Run () {for
(int i =; I < i++) {
Sy Stem.out.println (Myobject.getinstance (). Hashcode ());}}}
Run class
Package 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 mythread ();
T.start ();
T.start ();
T.start ();
T.start ();
T.start ();
}
Run Result:
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
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.day.singleton.ep;
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://...:/wechat_?useunicode=true&characterencoding=utf-";
String name = "root";
String password = "";
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.day.singleton.ep;
public class Mythread extends Thread {
@Override public
void Run () {for
(int i =; I < i++) {
System . Out.println (MyObject.connectionFactory.getConnection (). Hashcode ());}}}
Run class
Package 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 mythread ();
T.start ();
T.start ();
T.start ();
T.start ();
T.start ();
}
Run results
1 called the construction of the 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
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.day.singleton.ep;
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://...:/wechat_?useunicode=true&characterencoding=utf-";
String name = "root";
String password = "";
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.day.singleton.ep;
public class Mythread extends Thread {
@Override public
void Run () {for
(int i =; I < i++) {
System . Out.println (Myobject.getconnection (). Hashcode ());}}}
Results
1 called the construction of the 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
The above summarizes the various situations and solutions that are encountered when the simple mode is combined with multithreading for later use.