This is the third day of my participation in the August More text Challenge. For details, see:August is more challenging

Singleton patterns are one of the simplest design patterns. This type of design pattern is a creation pattern that provides an optimal 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 objects directly, without the need to instantiate objects of the class.

Note:

  1. A singleton class can have only one instance.
  2. A singleton class must create its own unique instance.
  3. The singleton class must provide this instance for all other objects.

introduce

describe parsing
intentions Ensure that there is only one instance of a class and provide a global point of access to it.
Mainly to solve A globally used class is created and destroyed frequently.
When to use When you want to control the number of instances and save system resources.
How to solve Check whether the system already has this singleton, return if it does, create it if it does not.
The key code Constructors are private.
Examples of application 1. There is only one head teacher in each class. 2, Windows is multi-process multi-threaded, in the operation of a file, it is inevitable that multiple processes or threads at the same time operation of a file phenomenon, so all the file processing must be carried out through a unique instance. 3, some device managers are often designed for singleton mode, such as a computer with two printers, in the output of the time to deal with two printers can not print the same file.
advantages 1. Having only one instance in memory reduces memory overhead, especially when instances are frequently created and destroyed (such as the MSM home page cache). 2. Avoid multiple use of resources (such as writing files).
disadvantages No interfaces, no inheritance, and in conflict with the single responsibility principle, a class should only care about its internal logic, not how it is instantiated externally.
Usage scenarios 1, require the production of a unique serial number. 2, the WEB counter, not every refresh in the database to add a time, with singleton first cache. 3. The created object consumes too many resources, such as the CONNECTION between I/O and database.
Matters needing attention getInstance()Method requires a synchronization locksynchronized (Singleton.class)Prevent multi-threaded at the same time causedinstanceIs instantiated multiple times.

implementation

  1. We’re going to create oneSingleObjectClass.SingleObjectA class has its private constructor and a static instance of itself.SingleObjectClass provides a static method for the outside world to get a static instance of it.
  2. SingletonPatternDemoClass USESSingleObjectClass to get theSingleObject object.

Step 1

Create a Singleton class.

// Singleton. Java public class SingleObject {private static SingleObject instance = new SingleObject(); // Make the constructor private, Private SingleObject(){} public static SingleObject getInstance(){return instance; public static SingleObject getInstance(){return instance; } public void showMessage(){ System.out.println("Hello World!" ); }}Copy the code

Step 2

Gets a unique object from the Singleton class.

/ / SingletonPatternDemo. Java public class SingletonPatternDemo {public static void main (String [] args) {/ / illegal constructor // A compile-time error: constructor SingleObject() is invisible //SingleObject object = new SingleObject(); SingleObject Object = singleObject.getInstance (); // Display the message object.showMessage(); }}Copy the code

Step 3

Execute the program and print the result:

Hello World!
Copy the code

Several implementations of the singleton pattern

The singleton pattern can be implemented in several ways, as follows:

1, lazy, thread is not safe

Characteristics of the describe
Specifies whether Lazy is initialized is
Multi-threaded security or not no
Is it easy to implement is

This is the most basic implementation, and the biggest problem with this implementation is that it doesn’t support multithreading. It’s not technically a singleton mode, since it’s not synchronized.

This lazy loading mode obviously does not require thread safety, and multiple threads cannot work properly.

public class Singleton { private static Singleton instance; private Singleton (){} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}Copy the code

2, lazy, thread safe

Characteristics of the describe
Specifies whether Lazy is initialized is
Multi-threaded security or not is
Is it easy to implement is
advantages Initialize only on the first call to avoid memory waste.
disadvantages Synchronized is necessary to ensure singletons, but locking is inefficient
describe This method has good lazy loading and can work well in multithreading, but it is inefficient and does not need synchronization 99% of the time.
Applicable scenario The performance of getInstance() is not critical to the application (the method is used infrequently).
public class Singleton { private static Singleton instance; private Singleton (){} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; }}Copy the code

3, hungry han type

Characteristics of the describe
Specifies whether Lazy is initialized no
Multi-threaded security or not is
Is it easy to implement is
advantages Without a lock, the execution efficiency is improved.
disadvantages Class is initialized when it is loaded, wasting memory
describe This approach is common, but can easily generate garbage objects.

It uses the ClassLoader mechanism to avoid multi-threaded synchronization problems. However, instance is instantiated when the class is loaded. Although there are many reasons for class loading, most singletons call getInstance. However, it is not clear that there is any other way (or any other static method) for the class to be loaded, so initializing instance is not lazy loading.

public class Singleton { private static Singleton instance = new Singleton(); private Singleton (){} public static Singleton getInstance() { return instance; }}Copy the code

4, double check lock/double check lock (DCL, namely double-checked locking)

Characteristics of the describe
Specifies whether Lazy is initialized is
Multi-threaded security or not is
Is it easy to implement No, it is complicated
describe This method adopts double locking mechanism, which is safe and can maintain high performance in multithreaded situations.
Applicable scenario The performance of getInstance() is critical to your application.
JDK version Since JDK1.5
public class Singleton {  
    private volatile static Singleton singleton;  
    private Singleton () {}  
    public static Singleton getSingleton() {  
        if (singleton == null) {  
            synchronized (Singleton.class) {  
                if (singleton == null) {  
                    singleton = new Singleton();  
                }
            }
        }
        return singleton;  
    }  
}
Copy the code

Registration/static inner classes

Characteristics of the describe
Specifies whether Lazy is initialized is
Multi-threaded security or not is
Is it easy to implement No, normal difficulty
describe This method can achieve the same effect as the double-check lock method, but the implementation is simpler. Use delayed initialization for static fields, which should be used instead of double-locking. This mode is only suitable for static domains. The double-check mode can be used when the instance domain requires delayed initialization

This method also uses the ClassLoader mechanism to ensure that the instance is initialized with only one thread. It is different from the third method: If the Singleton class is loaded, the instance will be instantiated (without lazy loading). If the Singleton class is loaded, the instance will not be initialized. Because the SingletonHolder class is not actively used, the instance is instantiated by explicitly loading the SingletonHolder class only by explicitly calling the getInstance method. Imagine if instantiating instance is resource-intensive, so you want it to be loaded lazily, but on the other hand, you don’t want to instantiate it when the Singleton class is loaded, because there’s no guarantee that the Singleton class might be actively used elsewhere to be loaded, It is not appropriate to instantiate instance at this time. At this point, this approach makes more sense than the third approach.

public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; }}Copy the code

6, the enumeration

Characteristics of the describe
Specifies whether Lazy is initialized no
Multi-threaded security or not is
Is it easy to implement is
JDK version Since JDK1.5

This implementation has not been widely adopted, but it is the best way to implement the singleton pattern. It is more concise, automatically supports serialization, and absolutely prevents multiple instantiations. This approach, advocated by Effective Java author Josh Bloch, not only avoids multi-threaded synchronization problems, but also automatically supports serialization, preventing deserialization from recreating new objects and absolutely preventing multiple instantiations. However, since the enum feature was introduced later in JDK1.5, writing in this way is unfamiliar and rarely used in practice.

Private constructors cannot be called through Reflection Attack.

public enum Singleton {  
    INSTANCE;  
    public void whateverMethod() {  
    }  
}
Copy the code

conclusion

In general, the use of the first and second lazy way is not recommended, the use of the third hungry way is recommended. The fifth registration mode is used only when the lazy loading effect is explicitly implemented. When it comes to deserializing objects, you can try using the sixth enumeration method. If there are other special needs, consider using a fourth type of double lock.