Java singleton pattern

Keywords: Java Design Pattern Algorithm Singleton pattern

Java singleton pattern

Single case introduction

Singleton Pattern is one of the simplest design patterns in Java. This type of design 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.

Intent: ensure that a class has only one instance and provide a global access point to access it.

Main solution: a globally used class is frequently created and destroyed.

When to use: when you want to control the number of instances and save system resources.

How to solve it: judge whether the system already has this single instance. If yes, it will be returned. If not, it will be created.

Key code: constructors are private.

Application example:

  • 1. There is only one head teacher in a class.
  • 2. Windows is multi process and multi-threaded. When operating a file, it is inevitable that multiple processes or threads operate a file at the same time, so all files must be processed through a unique instance.

advantage:

  • 1. There is only one instance in memory, which reduces the memory overhead, especially the frequent creation and destruction of instances
  • 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:

Creating an object consumes too many resources, such as the connection between I/O and database.

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

Singletons are also divided into lazy mode (thread unsafe) and hungry mode (thread safe)

The difference is:

The object is created the first time lazy mode is called

Hungry man mode creates objects when classes are loaded

Usage scenario:

Lazy mode is to create an object when it is needed, while hungry mode is to create this object when the program is loaded

Hungry man model

//Single case starvation mode
public class Single {
    //Create a Single object
    private static Single instance = new Single();

    //Make the constructor private so that the class will not be instantiated
    private Single(){}

    //Gets the only available object
    public static Single getInstance(){
        return instance;
    }

    public  void show(){
        System.out.println("I'm a single case:Hungry man model");
    }

}

test

public class test {

    public static void main(String[] args) {
        Single obj = Single.getInstance();
        obj.show();
    }
}

You can see why threads are safe: objects are created when the class is loaded, and there is no preemption of resources by multiple threads

Lazy mode

//Single case lazy mode
public class Single {
    private static Single instance;
    private Single (){}

    public static Single getInstance() {
        //If instance is empty, an object is created
        if (instance == null) {
            instance = new Single();
        }
        return instance;
    }
    public void show(){
        System.out.println("I'm a single case:Lazy mode");
    }
}

Note: the above code has no problem in single thread, but resource preemption will occur in multi thread

For example, if a thread accesses the getInstance() method at the same time, most threads are not blocked in if (instance == null)

Because new Single() takes time, instance == null instead of instance= Null, so

private static Single instance; Being overwritten back and forth leads to data loss

For example, thread 1 and thread 2 execute new Single(); When thread 2 comes in, if thread 2 new Single(); If thread 1 modified the data in the Single object before, thread 2 new Single(); After success, thread 1 will be overwritten, resulting in thread 1 data loss

Solution use synchronized code blocks in the thread to synchronize

Some people may want to use public static synchronized Single getInstance() directly. Of course, this is OK, but it will affect the performance

Best way double check lock

This method adopts double lock mechanism, which is safe and can maintain high performance in the case of multithreading.

//Single case lazy mode
public class Single {
    private  volatile static Single instance;
    private Single (){}

    public static  Single getInstance() {
        //If instance is empty, an object is created
        if (instance == null) {
        synchronized(Single.class){
            if (instance == null) {
                instance = new Single();
            }
          }
        }
        return instance;
    }
    public void show(){
        System.out.println("I'm a single case:Lazy mode");
    }
}

public class test {

    public static void main(String[] args) {
        Single obj = Single.getInstance();
        obj.show();
    }
}
Like - collect - pay attention - easy to review and receive the latest content in the future If you have other questions to discuss in the comment area - or send me a private letter - you will reply as soon as you receive them In case of infringement, please contact me by private letter Thank you for your cooperation. I hope my efforts will be helpful to you^_^

Posted by RGBlackmore on Wed, 06 Oct 2021 16:06:25 -0700