Background note: In the process of Android service startup, the corresponding time of service startup was investigated and the singleton initialization was slow, so I guess there may be a problem with singleton writing, so I sorted out the singleton writing method for reference.

Use recommendation: Finally, considering the factors such as thread safety, efficiency and simple writing method, we recommend using six, double check (DCL) or seven, static inner class

1. Hungry (static constant)

`class King { private static final King kingInstance = new King();

static King getInstance() {
    return kingInstance;
}


private King() {
}
Copy the code

} `

Advantages: This is a simpler way to write, which is to complete the instantiation when the class is loaded. Thread synchronization issues are avoided.

Disadvantages: Instantiation is done when the class is loaded, not Lazy Loading. If the instance is never used, then memory is wasted.

2, Hungry (static code block)

`class King { private static King kingInstance;

static {
    kingInstance = new King();
}

private King() {
}

public static King getKingInstance() {
    return kingInstance;
}
Copy the code

} `

Advantages: This is a simpler way to write, which is to complete the instantiation when the class is loaded. Thread synchronization issues are avoided.

Disadvantages: Instantiation is done when the class is loaded, not Lazy Loading. If the instance is never used, then memory is wasted.

Three, lazy (thread is not safe)

`public class King { private static King kingInstance;

private King() {
}

public static King getKingInstance() {
    if (kingInstance == null) {
        kingInstance = new King();
    }
    return kingInstance;
}
Copy the code

} ‘Advantages: lazy loading, loading only when used.

Disadvantages: But can only be used in a single thread. If, in multithreading, one thread enters an if (singleton == null) statement block and another thread passes the statement before it can proceed, multiple instances are created. Therefore, this approach cannot be used in multithreaded environments.

Four, lazy (thread safety)

`public class King { private static King kingInstance;

private King() {
}

public static synchronized King getKingInstance() {
    if (kingInstance == null) {
        kingInstance = new King();
    }
    return kingInstance;
}
Copy the code

} ‘advantages: lazy loading, only when used will load, get singleton method with synchronization lock, ensure thread safety.

Disadvantages: Inefficient, every thread that wants to get an instance of a class needs to execute the getInstance() method in synchronization.

Lazy (thread-safe, synchronized code block)

`public class King { private static King kingInstance;

private King() {
}

public static King getKingInstance() {
    if (kingInstance == null) {
        synchronized (King.class) {
            kingInstance = new King();
        }
    }
    return kingInstance;
}
Copy the code

} ‘advantages: improved the fourth kind of inefficient problem.

Disadvantages: Singletons are not fully guaranteed. If one thread enters an if (singleton == null) statement block and another thread passes the statement before it can proceed, multiple instances can be created.

Vi. Double Check (DCL)

`public class King {

private static volatile King kingInstance;

private King() {
}

public static King getKingInstance() {
    if (kingInstance == null) {
        synchronized (King.class) {
            if (kingInstance == null){
                kingInstance = new King();
            }
        }
    }
    return kingInstance;
}
Copy the code

} ‘Advantages: thread-safe; Lazy loading; High efficiency.

Cons: Not available with JDK < 1.5

Why not: JDK 1.5 and later fixes the volatile keyword, which can cause inefficient system performance by masking code optimizations made by the Java virtual machine.

The picture

Static inner class

`public class King {

private King() {
}

private static class KingInstance{
    private static final King KINGINSTANCE = new King();
}

public static King getInstance(){
    return KingInstance.KINGINSTANCE;
}
Copy the code

} ‘advantages: avoid thread insecurity, delay loading, high efficiency.

Disadvantages: None, most recommended.

Features: This approach is similar to, but different from, hangry.

Both use a classloading mechanism to ensure that only one thread initializes instances. The difference is that the Singleton class is instantiated as soon as it is loaded without lazy-loading, while the static inner class is not instantiated as soon as the Singleton class is loaded. Instead, the getInstance method is called when it needs to be instantiated. The SingletonInstance class is loaded to complete the Singleton instantiation. The static properties of a class are initialized only when the class is first loaded, so the JVM helps us keep our threads safe from entering while the class is initialized.

Enumeration /**

  • The enumeration

*/ public enum King { KINGINSTANCE; } Benefits: Not only avoids multithreaded synchronization problems, but also prevents deserialization from recreating new objects.

Cons: not available until JDK 1.5.

Use containers to implement singleton patterns (you can use them to manage singletons, if you are interested)

class InstanceManager { private static Map<String, Object> objectMap = new HashMap<>(); private InstanceManager(){} public static void registerService(String key,Object instance){ if (!objectMap.containsKey(key)){ objectMap.put(key,instance); } } public static Object getService(String key){ return objectMap.get(key); } }

/ * *

  • use
  • I won’t post the Dog class
  • Just write your own
  • You can run it to see if the printed addresses are consistent

*/ class Test { public static void main(String[] args) {

    InstanceManager .registerService("dog", new Dog());

    Dog dog = (Dog) InstanceManager .getService("dog");
    Dog dog2 = (Dog) InstanceManager .getService("dog");
    Dog dog3 = (Dog) InstanceManager .getService("dog");
    Dog dog4 = (Dog) InstanceManager .getService("dog");

    System.out.println(dog);
    System.out.println(dog2);
    System.out.println(dog3);
    System.out.println(dog4);
}
Copy the code

} Advantage: At the beginning of the program, multiple singleton types are injected into a unified management class, and objects of the corresponding type are obtained according to the key when used. In this way, we can manage multiple types of singletons, and we can use a unified interface to obtain operations, reducing the user’s use cost, but also to hide the specific implementation of the user, reduce the degree of coupling.

Disadvantages: not often used, some trouble

Summary 1: Efficiency comparison of nine singleton modes:

Example 2: Singleton use in Android source code:

Advantages and disadvantages of design pattern 3: Advantages and disadvantages of the singleton itself:

The original technology small program address: mp.weixin.qq.com/s/WxG8LHNJV…