Article catalogue
Design mode - singleton mode
What is singleton mode?
This pattern involves a single class that is responsible for creating its own objects while ensuring that only a single object is created. This class provides a way to access its unique object, which can be accessed directly without instantiating the object of this class.
1. Create an instance in the class, and create only one instance
2. If you want to call this object outside the class, you must call getInstance method to get the instance. The advantage is to reduce the overhead of creating and destroying objects
3. Only the unique instance provided by the class can be obtained
Lazy mode
Explain that a lazy man is lazy loading. When a class is loaded, it will not create an instance. It will only be created when it is called for the first time.
public class Singleton { /** * The following is the code of lazy mode */ // Thread safety problems will arise. Double check lock is used to ensure safety private static Singleton instance = null; // The class loading process does not create an instance, and the instance is set to null public Singleton() { } public static Singleton getInstance(){ // An instance is not created until the class is called for the first time if(instance==null){ return instance = new Singleton(); } // The instance created above is used for each subsequent instance call return instance; } }
Benefits: instances are created only when resources are called, so resources are saved.
Disadvantages: lazy mode brings thread safety problems
If multiple threads obtain instances at the same time, they are obtained for the first time. Execute the new instance in the if(instance==null) statement, so multiple instances will be created.
How to solve the thread safety problem?
1. Use double check lock
First if(instance==null)
First judge whether the instance exists, and then lock it if it does not exist
Second if(instance==null)
When multiple threads call the object for the first time, only one thread can enter to avoid creating multiple objects
public static Singleton getInstance(){ if (instance==null) { // First judge whether the instance exists, and then lock it if it does not exist synchronized (Singleton.class) { if(instance==null){// In the case of multithreading, only one can enter, avoiding the creation of multiple objects. return instance = new Singleton(); } } } return instance; }
2.volatile modifies the instance object and prohibits instruction reordering
private volatile static Singleton instance = null;
Instance = new Singleton is actually divided into three steps
1. Allocate memory space for new Singleton
2. Initialize object instance
3. The instance variable points to this memory address
The initialization time is a little slow, so the JVM instructions are rearranged and the order is changed from 1 - > 3 - > 2. In the case of single thread, there is no problem. However, in the case of multithreading, the first thread goes in and executes 1-3. At this time, an instance of the second thread is not null and directly returns the uninitialized instance object, which obviously causes thread safety problems.
So use volatile to prevent instruction rearrangement.
Thread safe lazy mode
public class Singleton { /** * The following is the code of lazy mode */ // There will be thread safety problems. Double check lock is used to ensure safety, and volatile is used to prohibit instruction reordering private volatile static Singleton instance = null; public Singleton() { } public static Singleton getInstance(){ if (instance==null) { synchronized (Singleton.class) { if(instance==null){ return instance = new Singleton(); } } } return instance; } }
Hungry man model
Understand the hungry man. Because he is too hungry, he wants to eat as soon as he gets something. Here is the process of class loading, so he can directly create a unique instance.
Benefits: no thread safety issues
Disadvantages: unlike lazy mode calling to create an instance, this is to create an instance when the class is loaded, so if it has not been called, you have to create an instance, which wastes resources.
public class Singleton { private static Singleton instance = new Singleton(); public Singleton() { } // Call the method to get the instance, only read, so there is no thread safety problem public static Singleton getInstance(){ return instance; } }