reference resources
Singleton pattern of JAVA design pattern
Singleton mode
Type: create type
Ensure that there is at most one instance of a class and provide a global access point
The singleton mode has the following characteristics:
- A singleton class can only have one instance.
- A singleton class must create its own unique instance.
- A singleton class must provide this instance to all other objects.
Measures taken:
By limiting the constructor to private, the class is prevented from being instantiated externally (for the time being, there is no reflection mechanism)
Within the scope of the same virtual machine, the unique instance of Singleton can only be accessed through the getInstance() method.
Hungry Han type
Relatively speaking, it needs less consideration, because its mechanism makes it inherently thread safe, so it is put in the first place
package Singleton mode.singleton; public class PreloadSingleton { public static PreloadSingleton instance = new PreloadSingleton(); //Avoid the class being instantiated externally private PreloadSingleton() { }; public static PreloadSingleton getInstance() { return instance; } }
Lazy type
Version 1.0
Basically, a new instance is created when the getInstance method is called for the first time
package Singleton mode.singleton; public class LazyLoadSingleton { private static LazyLoadSingleton instance=null; private LazyLoadSingleton(){ } public static LazyLoadSingleton getInstance() { if(instance==null) { instance=new LazyLoadSingleton(); } return instance; } }
However, it is thread unsafe, and multiple LazyLoadSingleton instances are likely to occur in a concurrent environment
Version 2.0
Thread synchronization is used to ensure thread safety
However, if the getInstance() method is called frequently, the thread will wake up and block whether the instance is initialized or not.
package Singleton mode.singleton; public class LazyLoadSingleton { private static LazyLoadSingleton instance=null; private LazyLoadSingleton(){ } public static synchronized LazyLoadSingleton getInstance() { if(instance==null) { instance=new LazyLoadSingleton(); } return instance; } }
Version 3.0
Add synchronized to the if(instance==null) judgment statement to ensure that the lock is added only when the instance is not instantiated
package Singleton mode.singleton; public class LazyLoadSingleton { private static LazyLoadSingleton instance=null; private LazyLoadSingleton(){ } public static synchronized LazyLoadSingleton getInstance() { if(instance==null) { synchronized (LazyLoadSingleton.class){ if(instance==null) { instance=new LazyLoadSingleton(); } } } return instance; } }
Ultimate version
new an object has code execution order, which cannot be guaranteed in a concurrent environment
Therefore, we need to use another keyword volatile to ensure the order of the object instantiation process.
memory=allocate();//1: Initialize memory space
ctorInstance(memory);//2: Initialize object
instance=memory();//3: Set instance to point to the memory address just allocated
package Singleton mode.singleton; public class LazyLoadSingleton { private static volatile LazyLoadSingleton instance=null; private LazyLoadSingleton(){ } public static synchronized LazyLoadSingleton getInstance() { if(instance==null) { synchronized (LazyLoadSingleton.class){ if(instance==null) { instance=new LazyLoadSingleton(); } } } return instance; } }
summary
Thread safe:
Hungry Han style is inherently thread safe and can be directly used for multithreading without problems,
Lazy style itself is non thread safe. There are several ways to achieve thread safety. These three implementations are different in resource loading and performance.
Resource loading and performance:
Hungry Chinese instantiates a static object at the same time as the class is created. No matter whether this single instance will be used later, it will occupy a certain memory, but correspondingly, it will be faster at the first call because its resources have been initialized,
As the name suggests, the lazy type will delay loading, and the object will be instantiated only when the singleton is used for the first time. Initialization is required for the first call. If there is more work to be done, there will be some delay in performance, and then it will be the same as the hungry type.