Detailed explanation of single case mode

Posted by Senate on Mon, 20 Dec 2021 11:42:55 +0100

What is singleton mode?

introduce

The design pattern of singleton pattern is a creation pattern, which provides the best way to create objects. 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.

be careful

1,A 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.

advantage:

1,There is only one instance in memory, which reduces the memory overhead, especially the frequent creation and destruction of instances (such as the homepage page cache of the school of management).
2,Avoid multiple occupation of resources (such as writing files). 

Disadvantages: there is no interface and cannot be inherited, which conflicts with the principle of single responsibility. A class should only care about the internal logic, not how to instantiate it outside.

Usage scenario:

1,A unique serial number is required for production.
2,WEB The counters in do not need to be added to the database every time they are refreshed, but are cached first with a single instance.
3,Creating an object consumes too many resources, such as I/O Connection with database, etc.

Note: the getInstance() method needs to use the synchronization lock synchronized (Singleton.class) to prevent multiple threads from entering at the same time, causing the instance to be instantiated multiple times.

realization

We will create a OneObject class. The OneObject class has its private constructor and a static instance of itself.
The OneObject class provides a static method for the outside world to obtain its static instance. The OneObjectDemo class uses the OneObject class to get the OneObject object.

Step 1: create a OneObject class

public class OneObject {
    //Create an object of OneObject
    private static OneObject instance = new OneObject();
    //Encapsulate the constructor so that the class will not be instantiated
    private OneObject(){}
    //Get unique available objects
    public static OneObject getInstance(){
        return instance;
    }
    public void showMessage(){
        System.out.println("hello world!");
    }
}

Step 2: get a unique object from the OneObject class.

public class OneObjectDemo {
    public static void main(String[] args) {
        //Compile time error: constructor SingleObject() is not visible
        //SingleObject object = new SingleObject();

        //Get unique available objects
        OneObject oneObject = OneObject.getInstance();
        //Print hello world
        oneObject.showMessage();
    }
}

Step 3: print results

hello world!

Several implementation methods of singleton mode

1. Lazy, thread unsafe

Description: This is the most basic implementation. The biggest problem with this implementation is that it does not support multithreading. Because there is no lock synchronized, it is not strictly a singleton mode. This approach does not require thread safety and does not work properly in multithreading.

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
  
    public static Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

2. Lazy, thread safe

Description: this method has good lazy loading and can work well in multithreading. However, the efficiency is very low and synchronization is not required in 99% of cases.
Advantages: initialize only after the first call to avoid memory waste.
Disadvantages: you must lock synchronized to ensure single instance, but locking will affect efficiency.

public class Singleton {  
    private static Singleton instance;  
    private Singleton (){}  
    public static synchronized Singleton getInstance() {  
    if (instance == null) {  
        instance = new Singleton();  
    }  
    return instance;  
    }  
}

3. Hungry Han style

Description: this method is commonly used, but it is easy to generate garbage objects.
Advantages: without locking, the execution efficiency will be improved.
Disadvantages: class initialization when loading, wasting memory.

Based on the classloader mechanism, it avoids the synchronization problem of multiple threads. However, instance is instantiated when class loading. Although there are many reasons for class loading, most of them call getInstance method in singleton mode, However, it is not certain that there are other ways (or other static methods) to cause class loading. At this time, initializing instance obviously does not achieve the effect of lazy loading.

public class Singleton {  
    private static Singleton instance = new Singleton();  
    private Singleton (){}  
    public static Singleton getInstance() {  
    return instance;  
    }  
}

4. Double checked lock (DCL, double checked locking)

JDK version: jdk1 5 cases

Description: this method adopts double lock mechanism, which is safe and can maintain high performance in the case of multithreading. The performance of getInstance() is critical to the application.

public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton (){}  
    public static Singleton getSingleton() {  
    if (singleton == null) {  
        synchronized (Singleton.class) {  
        if (singleton == null) {  
            singleton = new Singleton();  
        }  
        }  
    }  
    return singleton;  
    }  
}

summary

Generally, the first and second lazy ways are not recommended, and the third hungry way is recommended. If there are other special requirements, the fourth double check lock mode can be considered.

Topics: Java Design Pattern Singleton pattern