1 Singleton mode description

The singleton pattern is one of the most widely used, in which the class of a singleton object must be guaranteed to have only one instance. Many times the entire system only needs to have one global object, which helps us coordinate the behavior of the system as a whole. For example, creating an object consumes too many resources. For example, if you want to access IO and database resources, you need to use the singleton mode

2 Singleton schema definition

Ensure that a class has only one instance and provides a global access point.

Singleton UML class diagram:

In the figure, Client is the Client and Singletion is the Singleton class. The instance object is obtained by calling Singleton.getInstance().

3 Application scenarios of the singleton mode

In a system, a class is required to have one and only one object.

  • The entire project requires a shared access point or shared data.
  • Creating an object consumes too many resources, such as access to I/O and databases.
  • Utility class object.

4 Example of using singleton mode

The key points to realize the singleton pattern are as follows:

  • Constructors are not open to the publicPrivate;
  • Return a singleton class object through a static method or enumeration;
  • Ensure that there is one and only one object for a singleton class, especially in multithreaded environments;
  • Ensure that singleton class objects are not rebuilt when deserialized.

There are several ways to write the singleton pattern. Let’s look at each one:

4.1 Hungry And Hungry Mode

public class Singleton { private static Singleton mInstance = new Singleton(); // Constructor privateSingletonPublic static Singleton (){// Public static Singleton (){// Public static Singleton ()getInstance() {returnmInstance; }}Copy the code

This way the initialization is done at class loading time, so class loading is slow, but object retrieval is fast. This method is based on the class loading mechanism and avoids the synchronization problem of multiple threads. If the instance is never used, memory is wasted.

4.2 Slacker mode

Lazy mode declares a static object that is initialized the first time the user calls it. The hunk mode is initialized when static objects are declared. There are two implementations of slacker mode:

4.2.1 (Thread Unsafe)
public class Singleton {
    private static Singleton mInstance;
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (null == mInstance){
            mInstance = new Singleton();
        }
        returnmInstance; }}Copy the code

This lazy mode, while saving resources, would then need to be instantiated the first time it was loaded, which would be a bit slower. But uniqueness is not guaranteed in multithreading.

4.2.2 (Thread Safety)
public class Singleton {
    private static Singleton mInstance;
    private Singleton() {
    }
    public static synchronized Singleton getInstance() {
        if (null == mInstance){
            mInstance = new Singleton();
        }
        returnmInstance; }}Copy the code

We can find that the synchronized keyword is added to getInstance method, that is, getInstance method is a synchronization method, which can ensure the uniqueness of singleton object in the case of multi-threading. Each call to the getInstance method causes unnecessary synchronization overhead, which we don’t use most of the time. Therefore, this mode is generally not recommended.

4.3 Double-check Mode (DCL)

The advantage of Double Check Lock(DCL) is that the singleton can be instantiated only when needed, and the thread safety can be ensured. GetInstance is not synchronized after the singleton is initialized. The following is an example:

public class Singleton {
    private volatile static Singleton mInstance;
    private Singleton() {
    }
    public static Singleton getInstance() {
        if (null == mInstance) {
            synchronized (Singleton.class) {
                if(null == mInstance) { mInstance = new Singleton(); }}}returnmInstance; }}Copy the code

We can see that mInstance is nulled twice in the getInstance method. The first judgment is mainly to avoid unnecessary synchronization, and the second judgment is to create an instance in the case of NULL. Because in some cases a DCL failure can occur, you can use the volatile keyword to handle this problem. The use of volatile can have a significant or minor performance impact, but the correctness of the program may be worth the performance sacrifice.

Advantages of DCL: High efficiency in resource utilization. Store objects are instantiated only when getInstance is executed for the first time. Disadvantages of DCL: the reaction of DCL is slow at first loading, and it also has some disadvantages in high concurrency environment.

4.4 Singleton pattern for static inner classes

public class Singleton {
    private Singleton() {
    }
    public static Singleton getInstance() {
        returnSingletonHoler.sInstance; } private static class SingletonHoler{ private static final Singleton sInstance = new Singleton(); }}Copy the code

The unique feature of Java static inner classes is that internal static classes are not loaded when they are loaded, but are loaded when they are used. SInstance is not initialized the first time the Singleton class is loaded, only the first time the getInstance method is called and the virtual machine loads the SingletonHolder and initializes the sInstance. This ensures not only thread-safety, but also the uniqueness of the Singleton class. Therefore, the static inner class singleton pattern is recommended.

4.5 Enumerating singleton modes

public enum Singleton {
    INSTANCE;
}
Copy the code

External calls from Singleton.getInstance are now singleton. INSTANCE.

The default enumeration instances are created thread-safe and singleton in any case. Enumerating singletons has the advantage of being simple, but has the disadvantage of being unreadable.

5 concludes

Singletons are frequently used, and there is usually no high concurrency on our client, so it doesn’t matter which way you choose. For efficiency, the singleton pattern of static inner classes and the singleton pattern of the DCL are recommended.

Advantages:

  • Since the singleton pattern has only one instance in memory, the advantage of the singleton pattern is to reduce the memory overhead, especially when an object needs to be created and destroyed frequently and performance cannot be optimized when it is created or destroyed.
  • Because the singleton mode generates only one instance, it reduces the system performance overhead. When more resources are needed to generate an object, such as reading configuration or generating other dependent objects, the singleton can be generated directly when the application is started and then permanently resident.
  • The singleton mode can avoid multiple operations on resources, such as operations on a file. Because only one instance exists in memory, simultaneous operations on the same resource file are avoided.
  • The singleton pattern allows you to set up global access points in the system to optimize and share resource access. For example, you can design a singleton class that is responsible for mapping all data tables.

Disadvantages:

  • The singleton pattern generally has no interface and is difficult to extend unless you modify the code.
  • If a singleton object holdsContext, it is easy to cause memory leaks, in which case you need to pay attention to what is passed to the singletonContextIt is best toApplication Context.