A single example of design pattern

Posted by simonsays on Sat, 19 Feb 2022 16:03:46 +0100

Singleton mode

Introduction to single example design mode

The so-called class singleton design pattern is to take certain methods to ensure that there can only be one object instance for a class in the whole software idea, and the class only provides a method to obtain its object instance (static method).

The singleton mode can be implemented in seven ways:

  • Hungry Han formula (static constant)
  • Hungry Chinese style (static code block) recommendation
  • Lazy (thread unsafe)
  • Lazy (thread unsafe, thread synchronization method)
  • Double check recommendation
  • Static internal class recommendation
  • enumeration

Hungry Han formula (static constant)

Application example of hungry Han formula (static constant)

Steps:

  1. Constructor Privatization (prevent new)
  2. Class
  3. Expose a static public method

Code implementation:

public class SingletonTest01 {

    public static void main(String[] args) {
        //Get two Singleton objects
        Singleton singleton1 = Singleton.getSingleton();
        Singleton singleton2 = Singleton.getSingleton();
        //Output true to prove that the objects obtained twice are the same
        System.out.println(singleton1 == singleton2);
        System.out.println("singleton1.hashCode() = " + singleton1.hashCode());
        System.out.println("singleton1.hashCode() = " + singleton2.hashCode());
    }
}

class Singleton{
    //1. Create object instances within this class
    private static final Singleton instance = new Singleton();
    //2. The constructor is privatized and no external new is provided
    private Singleton(){}
    //3. Provide a common static method to return the instance object
    public static Singleton getSingleton(){
        return instance;
    }
}

Hungry Chinese style (static code block)

Description of advantages and disadvantages:

  • Advantages: this method is very simple, that is, instantiation is completed when the class is loaded. Thread synchronization problems are avoided
  • Disadvantages: the instantiation is completed when the class is loaded, which does not achieve the effect of Lazy Loading. If you have never used this instance from beginning to end, it will cause a waste of memory
  • Conclusion: This singleton mode can be used on the premise that this class must be used at least once, otherwise it will cause a waste of memory.

Starving Han style (static code block) application case

public class SingletonTest02 {

    public static void main(String[] args) {
        //Get two Singleton objects
        Singleton02 singleton1 = Singleton02.getSingleton02();
        Singleton02 singleton2 = Singleton02.getSingleton02();
        //Get the object true twice, and the output is the same
        System.out.println(singleton1 == singleton2);
        System.out.println("singleton1.hashCode() = " + singleton1.hashCode());
        System.out.println("singleton1.hashCode() = " + singleton2.hashCode());
    }
}

class Singleton02 {

    private static Singleton02 instance;

    private Singleton02(){}

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

    public static Singleton02 getSingleton02(){
        return instance;
    }
}

Lazy (thread unsafe)

Defect description:

  • If this method is used in multithreading development, it will cause thread insecurity
  • Reason: if thread A enters if and thread B grabs the thread execution right, then thread B will create an object, and thread A will also create an object when it comes back for execution
  • Summary: in actual development, lazy singleton mode is not recommended

Lazy (thread unsafe) application examples:

public class SingletonTest03 {
    public static void main(String[] args) {
        //Get two Singleton objects
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        //Output true to prove that the objects obtained twice are the same
        System.out.println(singleton1 == singleton2);
        System.out.println("singleton1.hashCode() = " + singleton1.hashCode());
        System.out.println("singleton1.hashCode() = " + singleton2.hashCode());
    }
}

class Singleton{

    private static Singleton instance;

    private Singleton(){}

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

Lazy (thread safe, synchronized code blocks)

Description of advantages and disadvantages:

  • Advantages: thread safety, realizing the effect of lazy loading
  • Disadvantages: when using multithreading, multiple threads want to get this object, and each time they need to wait for the previous thread
  • Conclusion: this method is not recommended in actual development

Lazy (thread safety, synchronous code block) application examples:

public class SingletonTest04 {
    public static void main(String[] args) {
        //Get two Singleton objects
        Singleton04 singleton1 = Singleton04.getInstance();
        Singleton04 singleton2 = Singleton04.getInstance();
        //Output true to prove that the objects obtained twice are the same
        System.out.println(singleton1 == singleton2);
        System.out.println("singleton1.hashCode() = " + singleton1.hashCode());
        System.out.println("singleton1.hashCode() = " + singleton2.hashCode());
    }
}

class Singleton04{

    private static Singleton04 instance;

    private Singleton04(){}

    /**
     * Add synchronous processing code to solve thread safety problems
     * But it's less efficient
     * @return
     */
    public static synchronized Singleton04 getInstance(){
        if(instance == null){
            instance = new Singleton04();
        }
        return instance;
    }
}

duplication check

Description of advantages:

  • This method is often used in development. In the following code, if is checked twice to ensure thread safety
  • Advantages: thread safety, delayed loading (lazy loading) and high efficiency
  • Conclusion: this single case design is recommended in practical development

Double check application example:

public class SingletonTest05 {
    public static void main(String[] args) {
        //Get two Singleton objects
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        //Output true to prove that the objects obtained twice are the same
        System.out.println(singleton1 == singleton2);
        System.out.println("singleton1.hashCode() = " + singleton1.hashCode());
        System.out.println("singleton1.hashCode() = " + singleton2.hashCode());
    }
}

class Singleton{

    private static volatile Singleton instance;

    private Singleton(){}

    /**
     * Add double check code to solve the thread problem and lazy loading problem at the same time
     * At the same time, the efficiency is guaranteed
     * @return
     */
    public static Singleton getInstance(){
        if(instance == null){
            synchronized (Singleton.class) {
                if(instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}

Static inner class

Description of advantages:

  • This method adopts the mechanism of class loading to ensure that there is only one thread when initializing the instance.
  • The static internal class method does not instantiate the Singleton class immediately when it is loaded, but calls the getInstance method when instantiation is needed to load the Singleton class, so as to complete the instantiation of Singleton
  • The static properties of the class will only be initialized when the class is loaded for the first time, so here, the JVM helps us ensure the safety of threads. When the class is initialized, other threads cannot enter
  • Advantages: thread insecurity is avoided, delayed loading is realized by using the characteristics of static internal classes, and the efficiency is high
  • Conclusion: it is recommended to use

Static internal class application instance:

public class SingletonTest06 {
    public static void main(String[] args) {
        //Get two Singleton objects
        Singleton singleton1 = Singleton.getInstance();
        Singleton singleton2 = Singleton.getInstance();
        //Output true to prove that the objects obtained twice are the same
        System.out.println(singleton1 == singleton2);
        System.out.println("singleton1.hashCode() = " + singleton1.hashCode());
        System.out.println("singleton1.hashCode() = " + singleton2.hashCode());
    }
}

class Singleton{

    private Singleton(){}
	//Write a static inner class with a static attribute Singleton
    private static class SingletonInstance{
        private final static Singleton INSTANCE = new Singleton();
    }
	//Provide a method to get common property and directly return singletoninstance INSTANCE
    public static Singleton getInstance(){
        return SingletonInstance.INSTANCE;
    }
}

enumeration

Description of advantages and disadvantages:

  • With jdk1 5 to implement the singleton mode, which can not only avoid the problem of thread synchronization, but also prevent deserialization and re creation of new objects
  • Summary: Recommended

Enumerate application instances:

public class SingletonTest07 {
    public static void main(String[] args) {
        Singleton instance1 = Singleton.INSTANCE;
        Singleton instance2 = Singleton.INSTANCE;
        System.out.println(instance1 == instance2);
        System.out.println(instance1.hashCode());
        System.out.println(instance2.hashCode());
        instance1.test();
    }
}

enum Singleton{
    INSTANCE;	//attribute
    public void test(){	//method
        System.out.println("ok");
    }
}

Source code analysis of singleton mode in JDK application

In * * Java The Runtime under Lang package uses the singleton mode of hungry Han formula (static constant) * *

code:

public class Runtime {
    private static Runtime currentRuntime = new Runtime();

    /**
     * Returns the runtime object associated with the current Java application.
     * Most of the methods of class <code>Runtime</code> are instance
     * methods and must be invoked with respect to the current runtime object.
     *
     * @return  the <code>Runtime</code> object associated with the current
     *          Java application.
     * 		
     */
    public static Runtime getRuntime() {
        return currentRuntime;
    }
    /** Don't let anyone else instantiate this class */ 
    private Runtime() {}
    //There are many ways
}

Notes and details of singleton mode

  • The singleton mode ensures that there is only one object in the system memory, which saves system resources. For some objects that need to be created and destroyed frequently, the singleton mode can improve the system performance
  • When you want to instantiate a singleton class, you must remember to use the corresponding method to get the object instead of new
  • Singleton usage scenarios: objects that need to be created and destroyed frequently, objects that take too much time or resources to create objects (i.e. heavyweight objects), but are often used, tool objects, and objects that frequently access database files (such as data sources, session factories, etc.)

Topics: Java Programming Design Pattern Interview