Singleton mode (essence: control the number of instances)

Posted by KC8Alen on Sun, 06 Mar 2022 10:44:20 +0100

1. Foreword

There is a scenario where we need to read the attribute value from the configuration file and inject it into the java class. Should this class be new only once in the whole system!

Think about what design patterns can be realized!!

What is singleton mode

Singleton mode: its essence is to control the number of instances.
Mandarin: ensure that a class has only one instance and provide a global access point to access it.

An interface diagram of singleton mode:

Singleton: it is responsible for creating its own unique instance of singleton class and providing a getInstance method to allow external access to the unique instance of this class.

3. How to achieve

We have learned that there are two ways to implement singleton mode: lazy and hungry.

Implementation: privatize the construction method, provide the method to obtain the instance, turn the method to obtain the instance into static, and directly call this method with the class.

Define the properties of the storage instance. Define this attribute as static.

/**
Example of lazy singleton implementation
*/
public class Singleton{
    /**
    Define a variable to store the created class instance.
    */
    private static Singleton unqueInstance = null;
    /**
    Privatization construction method
    */
    private Singleton(){
        
    }
    /**
    Define a method to provide a class instance for the client
    */
    public static synchronized Singleton getInstance(){
        if(unqueInstance == null){
            unqueInstance = new Singleton();
        }
        return unqueInstance;
    }
}

/**
Hungry Han style
 Create directly
*/
public class Singleton{
    /**
    Define a variable to store the created class instance.
    */
   private static Singleton unqueInstance = new Singleton();
    /**
    Privatization construction method
    */
    private Singleton(){
        
    }
    /**
    Define a method to provide a class instance for the client
    */
    public static Singleton getInstance(){
        return unqueInstance;
    }
}

Lazy style: the idea of exchanging time for space, delaying loading and caching.
Hungry Chinese style: space for time.

We generally propose to delay loading to improve the performance of system initialization.
Sharp eyed people find that lazy style adds a synchronized keyword, which shows that lazy style is not thread safe.
Why?

When two requests come at the same time, two may be created.
So people put forward the first method, adding synchronized synchronization, but this greatly affects the performance. When multiple requests come at the same time, you need to wait.
At this time, the second method is proposed: double checking and locking. Instead of synchronizing every time you enter the getInstance method, you first do not synchronize. After entering the method, you first check whether the instance exists. If it does not exist, you enter the following synchronization block. This is the first check. After the instance is created, check whether the instance exists again. In this way, check whether the instance exists again. Thus, the time wasted in judging multiple times in the case of synchronization is reduced.

public class Singleton{
    /**
    Add volatile to the variable that holds the instance.
    */
    private volatile static Singleton instance = null;
    privat Singleton(){
        
    }
    public static Singleton getInstance(){
        //First check whether the instance exists. If it does not exist, enter the following synchronization block
        if (instance == null) {
            //Synchronization block, thread safe creation of instances.
            synchronized(Singleton.class){
                //Check whether the instance exists again. If it does not exist, the instance will be created.
                if (instance == null) {
                    instance = new Singleton();	
                }
            }
        }
        return instance;
    }
}

A keyword volatile is used here: the modified variable will not be cached by the local thread. All reads and writes to the variable are directly operated on the shared memory. This ensures that multiple threads can handle the variable correctly. (double checking and locking can only be implemented above jdk1.5). This keyword may shield some necessary code optimization in the virtual machine, and it is generally not recommended to use it in large quantities.

Better way:

public class Singleton{
    /**
    Class level inner class, that is, static member inner class. The instance of the inner class is the same as that of the outer class
    There is no binding relationship, and it will be loaded only when it is called, so delayed loading is realized
    */
    public static class SingletonHolder{
        /**
        Static initializer. The jvm ensures thread safety
        */
        private static Singleton instance = new Singleton();
    }
    
    private Singleton(){}
    
    public static Singleton getIntence(){
        return SingletonHolder.instance;
    }
}

The features of jvm are used.

Scope of singleton mode

When a virtual machine loads a singleton class through its ClassLoader, it will create an instance of the class.

!!! The singleton mode here is not applicable to the cluster environment.

Naming of singleton mode

It is suggested that the singleton pattern be named getInstance(). The return value of this method must be the type of the singleton class. Can have parameters.

When to use singleton mode

When you need to control that there can only be one instance of a class, and customers can only access it from one global access point, you can choose the singleton mode.

Finally, I recommend a Book: "grinding design mode". Xiaobai understands the record and modifies it slowly.

Topics: Java Design Pattern Singleton pattern