This is a typical hangovers Singleton, where instance instances are created when the Singleton class is loaded, requiring some upfront overhead of system resources. If the instance is not used later, it is a waste of system resources. There are no other problems

  private Singleton() {}

   private static Singleton instance = new Singleton();

   public static Singleton getInstance() {
       return instance;
   }
Copy the code

The lazy singleton mode will initialize the singleton only when it is used for the first time, which can save resources to a certain extent, but the response is slower. The synchronized keyword ensures the uniqueness of singletons in multi-threaded situations. However, after the singletons are initialized for the first time, the getInstance() method needs to be synchronized, which will cause unnecessary system overhead.

 private Singleton(){

   }
   private static Singleton instance;

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

In getInstance(), instance is first checked for non-null to avoid redundant synchronization, which also solves the problem of every synchronization in lazy singleton mode. Then instance is created if instance is empty. Of course, this step requires synchronization. Note that instance = new Singleton(); This line of code, whose execution can be broken down into a third step:

(1) Allocate memory for instance.

(2) Execute Singleton constructor to initialize instance.

(3) Set instance to the allocated memory.

However, before JDK1.5, the sequence of (2)(3) cannot be guaranteed. If the sequence of (1)(3)(2) is followed by (1)(3)(2), if thread A finishes (3) and (2) is not executed, it will be switched to thread B, because step (3) has been executed in thread A, thread B will directly take the instance that is not empty. This invalidates the double-checked locking judgment.

After JDK1.5, simply declare instance instances as follows: Private Volatile static Singleton instance; Adding the volatile modifier ensures that instance is read from main memory every time, avoiding the above problem but slightly affecting performance. This singleton pattern also creates a singleton on the first execution of getInstance(), but the first response is slightly slower.

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

Static inner class singleton pattern: In this way, the virtual machine will load the SingletonHolder class and initialize the instance only when the getInstance() method is called for the first time. This ensures thread synchronization and singleton uniqueness, which is much simpler than the double-checked locking singleton mode. This approach is recommended for implementing the singleton pattern.

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