Design mode - singleton mode

Posted by tensitY on Fri, 18 Feb 2022 10:48:38 +0100

1, Hungry Han style

  1. Constructor private
  2. Class
  3. Expose a static method

1. Static constant

  1. Test class
public class SingletonTest01{
	
	public static void main(String[] args){
		Singleton singleton = Singleton.getInstance();
		Singleton singleton1 = Singleton.getInstance();
		System.out.println(singleton == singleton1 );
	}
}
  1. Hungry Han formula (static variable)
package com.znb.singleton.demo01;

//Hungry Han formula (static variable)
public class Singleton {

    //1. Constructor private
    private Singleton(){}

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

    //3. Expose a static method
    public static Singleton getInstance(){
        return instance;
    }
}

2. Static code block

  1. Test class
public class SingletonTest01{
	
	public static void main(String[] args){
		Singleton singleton = Singleton.getInstance();
		Singleton singleton1 = Singleton.getInstance();
		System.out.println(singleton == singleton1 );
	}
}
  1. Hungry Han formula (static variable)
public class Singleton {

    //1. Constructor private
    private Singleton(){}

    //2. Create object instances within this class
    private static Singleton instance;

    static {
        //Create a singleton object in a static code block
        instance = new Singleton();
    }

    //3. Expose a static method
    public static Singleton getInstance(){
        return instance;
    }
}

2, Lazy style

1. Thread unsafe

//Lazy (thread unsafe)
public class Singleton {

    //1. Constructor private
    private Singleton(){}

    //2. Create object instances within this class
    private static Singleton instance;

    /**
     * 3.Expose a static method to the outside, and create an instance only when the method is used
     * Lazy style
     * @return
     */
    public static Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}

  1. Played the role of lazy Loading effect, but it can only be used under single thread.
  2. If a thread enters the if(singleton == null) judgment statement block and has not had time to execute, another thread also passes the judgment statement, multiple instances will be generated. Therefore, this method cannot be used in a multithreaded environment.
  3. Can't be used, breaking the singleton mode

2. Thread safety, method synchronization

//Lazy (thread safety, synchronization method)
public class Singleton {

    //Private constructor
    private Singleton(){}

    //2. Create object instances within this class
    private static Singleton instance;

    /**
     * 3.Expose a static method to the outside, and create an instance only when the method is used
     * Add code for synchronization
     * Lazy style
     * @return
     */
    public static synchronized Singleton getInstance(){
        if(instance == null){
            instance = new Singleton();
        }
        return instance;
    }
}
  1. The thread unsafe problem is solved.
  2. Low efficiency. When each thread wants to obtain an instance of a class, it needs to synchronize the execution of getInstance method, but this method only needs to execute the instantiation code once, and then execute this method to directly return to the instance object.
  3. Not recommended

3. The thread is unsafe and the code block is synchronized

package com.znb.singleton.demo05_lan;

//Lazy (thread safe, synchronous code block)
public class Singleton {

    //1. Constructor private
    private Singleton(){}

    //2. Create object instances within this class
    private static Singleton instance;

    /**
     * 3.Expose a static method to the outside, and create an instance only when the method is used
     * 
     * Lazy style
     * @return
     */
    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                instance = new Singleton();
            }
        }
        return instance;
    }
}

  1. This kind of synchronization does not play the role of thread synchronization
  2. out of commission

3, Double check

package com.znb.singleton.demo06_lan;

//Double test
public class Singleton {

    //1. Constructor private
    private Singleton(){}

    //2. Create object instances within this class
    private static volatile Singleton instance;

    /**
     * 3.There is a common method of adding code,
     * Solve the problem of thread safety and lazy loading at the same time
     * @return
     */
    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class){
                if (instance == null){
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

  1. If in the case of multithreading, threads a and b pass the first if judgment at the same time, then one of a or b enters the synchronization code block to create the instance object. When the latter enters the synchronization code block again, it makes the if judgment again. If it is found that the object has been created, it will not create a new object.
  2. Thread safety, delayed loading, high efficiency.
  3. Recommended use

4, Static inner class

//Static internal class, recommended
public class Singleton {

    //1. Constructor private
    private Singleton(){}

    //2. Static internal class, which has a static attribute Singleton
    private static class SingletonInstance{
        private static final Singleton INSTANCE = new Singleton();
    }

    /**
     * 3.Provide a common method
     */
    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

  1. Class loading mechanism is adopted to ensure that there is only one thread when initializing the instance.
  2. The static internal class method does not instantiate the Singleton class immediately when it is loaded. Instead, when instantiation is needed, call the getInstance method to load the Singleton class, so as to complete the instantiation of Singleton
  3. The static properties of the class will only be initialized when the class is loaded for the first time. Here, the JVM helps me ensure thread safety. When the class is initialized, other threads cannot enter.
  4. It avoids thread insecurity and uses the characteristics of static internal classes to realize delayed loading with high efficiency
  5. Recommended use

5, Enumeration

//enumeration
enum Singleton {
    INSTANCE;
    public void sayOK(){
        System.out.println("ok");
    }
}

  1. With jdk1 The enumeration added in 5 to realize the singleton mode can not only avoid the problem of multi-threaded synchronization, but also prevent the reverse sequence from re creating new objects
  2. Recommended use

6, Precautions for singleton mode

  1. The singleton mode ensures that there is only one object of this class in the system memory, which saves system resources. For some objects that need to be created and destroyed frequently, using the singleton mode can improve the system performance.
  2. When instantiating a singleton class, you must remember to use the corresponding method to get the object instead of new
  3. In the usage scenario of singleton mode, objects need to be created and destroyed frequently. Objects that take too much time or resources to create but are often used, tool objects, and objects that frequently access databases or files.

Topics: Java Singleton pattern