definition
Make sure there is only one instance of a class and provide a global access point.
Why do you want to use it
It is important for some classes to ensure that there is only one instance. For example, the Windows operating system in the Resource Manager, Recycle Bin and other tools must be guaranteed only one instance, or the system will have some unexpected exceptions.
Advantages
Because there is only one instance, it is easy to control its access rights, avoid excessive use of static variables, and so on.
Scope of application
When a class can have only one instance and the customer can access it from a well-known access point.
structure (UML)
The singleton pattern has a simple structure, with only one class: its constructor is private and provides a static method that returns an instance.
The UML of the singleton mode is simple:
Implement
Suppose now that you have a place that needs to be used in a singleton pattern, you might first think of writing this:
1 PackageCom.tony.singleton;2 3 /**4 * 1. Privatization of the constructor5 * 2, provide a method to return the instance (Global access point)6 * This method is called lazy-type7 */8 Public classSingleton01 {9 Private StaticSingleton01 instance =NULL;Ten //Privatization Constructor One PrivateSingleton01 () { A } - //Static Factory Method - Public StaticSingleton01 getinstance () { the if(Instance = =NULL){ -Instance =NewSingleton01 (); - } - returninstance; + } -}
But this method has another problem: Now the program is generally multi-threaded, in the case of concurrency may appear two instances!
Let's analyze this situation: There are now two threads (A, B) that call the GetInstance () method at the same time, and then an A thread discovers that instance is null. When a thread is ready to go to the new instance, the B thread also discovers that instance is null, so the B thread also goes to the new instance. In this case, there will be two instances.
How to solve it?
At this point we will think this is not simple, add a synchronized sync lock is not OK?!
1 PackageCom.tony.singleton;2 3 /**4 * 1. Privatization of the constructor5 * 2, provide a method to return the instance (Global access point)6 */7 Public classSINGLETON02 {8 Private StaticSingleton02 instance =NULL;9 //Privatization ConstructorTen PrivateSingleton02 () { One } A //Static Factory Method - Public Static synchronizedSingleton02 getinstance () { - if(Instance = =NULL){ theInstance =NewSingleton02 (); - } - returninstance; - } +}
OK problem solved! Synchronization This method is simple and easy to solve the concurrency problem of threads, but at the same time brings a new problem: the impact on performance. If getinstance () is frequently called, then you have to reconsider: you have to give it a sync lock before each call! You need to know that synchronizing a method can result in a 100 times-fold decrease in program execution, and only requires synchronization if the object is instantiated.
Well, since the trouble is in instantiating the object here, I'm going to instantiate this object when I load the ClassLoader, is that OK?
1 PackageCom.tony.singleton;2 3 /**4 * 5 * This is the way to do a hungry man style6 */7 Public classSingleton03 {8 //This class is instantiated when loaded by the ClassLoader9 Private StaticSingleton03 instance =NewSingleton03 ();Ten //Privatization Constructor One PrivateSingleton03 () { A } - //Static Factory Method - Public StaticSingleton03 getinstance () { the returninstance; - } -}
With this approach, we rely on the JVM to create this unique instance as soon as the class is loaded. The JVM guarantees that this instance must be created before any thread accesses the instance variable.
This approach is good, basically solves the above two problems: 1, concurrent access, 2, the impact on performance.
This approach is suitable for less complex instances. If the classes that need to be instantiated are complex, the burden on the JVM can be increased by being too heavy on creation and runtime.
Is there a way to delay loading and reduce the burden on the JVM in addition to solving the initial two problems? The answer is YES!
This method is called double detection lock. This time introduced a new thing: the volatile keyword.
1 PackageCom.tony.singleton;2 3 /**4 * Double detection lock5 * 6 */7 Public classSingleton04 {8 //add volatile keywords!!! 9 Private volatile StaticSingleton04 instance =NULL;Ten //Privatization Constructor One PrivateSingleton04 () { A } - //Static Factory Method - Public Static synchronizedSingleton04 getinstance () { the if(Instance = =NULL){ - //This code has only one chance of execution: only the first time it's completely executed. - synchronized(Singleton04.class){ - if(Instance = =NULL){ +Instance =NewSingleton04 (); - } + } A } at returninstance; - } -}
This time the code that synchronized synchronizes is only executed once, and also guarantees a delay load.
Summary
There are several ways to implement a singleton pattern, but these are some of the more common ones. General Master A hungry man type, lazy-type and double detection lock on the can.
Each of these have advantages and disadvantages, specific use of that there are specific circumstances specific analysis.
Lazy: can delay loading, but may have a large impact on performance.
Lazy: The performance impact is small, but can not delay loading.
Dual detection Lock: Can be delayed loading, only one time, but does not support the previous version of JDK1.4.
Reference documents
"Head First design mode"
"Design Mode"
Single-Case mode