Learning in singleton mode

Singleton mode

 
  for some classes, only one object instance is allowed, and a method to obtain its object instance [static method] is provided

Singleton pattern structure


  a singleton class declares a static method named getInstance to get an instance to return the same instance of its class.
  and its construction method needs to be hidden, that is, getInstance() is the only method that can get the instance
 

Embodiment in Java:

​  1. Add a private static member variable to the class to hold the singleton instance.

​  2. Declare a public static build method to get a singleton instance.

​  3. Implement "deferred initialization" in static methods. This method creates a new object the first time it is called and stores it in a static member variable. After that, the method returns the instance every time it is called.

​  4. Make the constructor of the class private. Class can still call constructors, but other objects cannot.

​  5. Check the client code and replace the call to the constructor of the singleton with a call to its static build method
 

 

classification

 

Hungry Han formula (static constant)

  hungry Chinese style is to directly new the instance in memory

class Singleton{
    //2. Create object instances within this class
    private final static Singleton instance = new Singleton();

    //1. Privatization of constructor
    private Singleton(){

    }

    //3. Provide public static methods to return instance objects
    public static Singleton getInstance(){
        return instance;
    }
}

public class SingletonTest {
    public static void main(String[] args) {
        Singleton instance1 = Singleton.getInstance();
        Singleton instance2 = instance1;

        System.out.println(instance1 == instance2);//true
        System.out.print(instance1.hashCode()+"|");
        System.out.println(instance2.hashCode());
        //1325547227|1325547227
    }
}

 
advantage:

  instantiation is completed during class loading to avoid thread synchronization

Disadvantages:

  the effect of Lazy Loading is not achieved

  if this instance is not used, it will cause a waste of memory
 

Hungry Chinese (static code block)

class Singleton{
    private static Singleton instance;


    private Singleton(){
    }

    //In a static code block, create a singleton object
    static {
        instance = new Singleton();
    }


    public static Singleton getInstance(){
        return instance;
    }
}

 

Lazy (thread unsafe)

  lazy means that the object is new in memory only when the instance is got.

class Singleton{
    private static Singleton instance;


    private Singleton(){
    }

    //Provide a static public method
    //When using this method, take the step of creating instance
    public static Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

Advantages and disadvantages:

  it has the effect of Lazy Loading. But it can only be used under single thread

  in multithreading, if a process enters the if judgment and has not yet been executed, and other threads also pass the judgment statement, multiple instances will be generated

In actual development, this method is not used

 

Lazy (thread safety, synchronization method)

class Singleton{
    private static Singleton instance;


    private Singleton(){
    }

    //Add synchronous processing code to solve the problem of thread insecurity
    public static synchronized Singleton getInstance(){
        if (instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

Advantages and disadvantages:

  solves the problem of thread insecurity

  but the efficiency is too low. When each thread wants to obtain the instance, it needs to synchronize when entering the getInstance method, and the method only needs to be executed once. If it needs to obtain the instance later, they can return directly.

 

Lazy (thread unsafe, synchronous code block)

class Singleton{
    private static Singleton instance;


    private Singleton(){
    }


    public static Singleton getInstance(){
        if (instance == null){
            //Add synchronous processing code to solve the problem of thread insecurity
            synchronized (Singleton.class) {
                instance = new Singleton();
            }
        }
        return instance;
    }
}

  the original intention is to improve the previous one

  but it does not play the role of thread synchronization. Because it is easy to generate multiple instances when entering the if judgment.
 

duplication check

class Singleton{
    private static volatile Singleton instance;

    private Singleton(){
    }

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

Description of advantages and disadvantages:

  double checking is often used in multithreading development. Two if judgments ensure thread safety.

  instantiate the code only once. Improve efficiency.

 

Static inner class

  features of static inner class:

   when loading a class, it will not be loaded. Ensure lazy loading.

   when calling, the class will be loaded [and only once]. Ensure thread safety

class Singleton{

    private Singleton(){
    }

    //Static inner class with a static attribute
    private static class SingletonInstance{
        private static final Singleton INSTANCE = new Singleton();
    }

    //Returns the static properties of the static inner class
    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

Advantages and disadvantages:

  class loading mechanism is adopted to ensure that there is only one thread for initialization

  static internal classes will not be instantiated immediately when external classes are loaded. SingletonInstance class will be loaded only when getInstance() is called to complete instantiation

 

enumeration

enum Singleton{
    INSTANCE;

    public void sayOK(){
        System.out.println("This is OK.");
    }
}

public class SingletonTest {
    public static void main(String[] args) {
        Singleton instance1 = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;

        System.out.println(instance1 == instance2);//true
        System.out.print(instance1.hashCode()+"|");
        System.out.println(instance2.hashCode());
        //1325547227|1325547227

        instance1.sayOK();//This is OK.
    }
}

Advantages and disadvantages:

  with the help of enumeration implementation, it can not only avoid the problem of multi-threaded synchronization, but also prevent the reproduction of deserialization and the creation of new objects.

​ ​  👍 It is also the way advocated by Josh Bloch, the author of Effective Java
 

Application scenario of singleton mode

  if a class in the program has only one instance available for all clients, the singleton mode can be used.

  if you need to control global variables more strictly, you can use singleton mode.
 

Advantages and disadvantages

  advantages:
​  ​  ✔️ You can guarantee that a class has only one instance
​  ​  ✔️ You have obtained a global access node to the instance
​​    ✔️ A singleton object is initialized only when it is first requested

  disadvantages:
​  ​  ❌ Singleton mode may mask bad design, such as too much mutual understanding between program components.
​  ​  ❌ This mode needs to be processed in a multi-threaded environment, so it is necessary to avoid multiple threads creating singleton objects multiple times.
​  ​  ❌ Singleton client code unit testing can be difficult because many test frameworks create mock objects in an inheritance based manner. Since the constructor of a singleton class is private, and most languages cannot override static methods, you need to think of ways to simulate singletons carefully. Either don't write test code at all, or don't use singleton mode.

Added by spiffy577 on Mon, 24 Jan 2022 18:15:11 +0200