The singleton pattern, also called the singleton pattern, is arguably the simplest of the design patterns. As the name implies, to create a unique and unique instantiated object.
Why do you do that? Because sometimes, we only need one object, and too many objects can cause unnecessary trouble. For example, thread pools, caches, printers, and registries can cause problems if there are multiple instances!
Introduce the singleton pattern
We introduce the singleton pattern with a small problem!
- How do I create an object? We all know that
new MyObject();
- When we need to create with another object, we just need to do it again
new MyObject();
Can be - Is code like the following correct?
public MyClass{
private MyClass() {}}Copy the code
- It looks like this is a legal definition, there are no grammatical errors. But if you think about it, you can only call the constructor within MyClass if you have a private constructor. We can’t instantiate it because we have to have an instance of Myclass to call the constructor, but no other class can get an instance of it. Is this a chicken-and-egg situation? Ha, ha, ha
- To solve this problem, we create a static method to get an instance of the MyClass class
public MyClass{
private MyClass() {}
public static MyClass getInstance() {
returnnew MyClass(); }}Copy the code
- We have added a static class method that returns an instance of an object that can be called externally because it is public. This actually implements a simple singleton pattern.
Implementation of classical singleton pattern
public class Singleton {
private static Singleton uniqueInstance;
private Singleton(){}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
returnuniqueInstance; }}Copy the code
- This implements a concept called lazy instance. Because when we don’t need an instance, that instance will never be instantiated.
Define a singleton pattern
Singleton pattern definition: Ensures that a class has only one instance and provides a global access point.
This definition should be easy to understand. Let’s use the class diagram to illustrate:
Problems with the classic one-piece model
The problem with the classical singleton pattern is that the first instantiation may end up with more than one object if it is accessed by different threads at the same time.
As shown, if two threads are interlaced in the same order as shown, two objects will be instantiated! This is the multithreading problem with the classical singleton pattern.
Solve multithreading problems in singleton mode
synchronize
Obviously one of the simplest solutions is to synchronize the getInstance method.
public class Singleton {
private static Singleton uniqueInstance;
private Singleton(){}
public static synchronized Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
returnuniqueInstance; }}Copy the code
This is obviously a good solution, but synchronization is inefficient.
Eager instantiation
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton(){}
public static synchronized Singleton getInstance() {
returnuniqueInstance; }}Copy the code
Before any thread accesses the uniqueInstance variable, we guarantee that the instance has already been created.
Double check locking
public class Singleton {
private volatile static Singleton uniqueInstance;
private Singleton() {}
public static Singleton getInstance() {
if (uniqueInstance == null) {
synchronized (Singleton.class) {
if(uniqueInstance == null) { uniqueInstance = new Singleton(); }}}returnuniqueInstance; }}Copy the code