The hungry singleton

public class Singleton { private static Singleton instence = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instence; }}Copy the code
  • Creating a single instance object as soon as the class is loaded into memory consumes memory resources.
  • Advantages: Fast object acquisition speed; Avoid multithreading synchronization problems.
  • Disadvantages: Slow class loading.

Hunhanian variant singleton (static inner class)

public class Singleton { private Singleton() { } private static class SingletonHolder{ private static final Singleton INSTANCE = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.INSTANCE; }}Copy the code
  • This SingleTon pattern is not initialized on the first class load, only the virtual machine loads the SingletonHolder and initializes the SingleTon instance on the first call to getInstance(). It is also thread-safe and recommended.
  • Advantages: Thread safety and resource saving
  • Disadvantages: slightly slow reaction on first loading

Why are static inner classes thread-safe?

First, let’s look at the advantages of static inner classes:

  • The inner class does not need to be loaded immediately when the outer class is loaded
  • The inner class is not loaded and INSTANCE is not initialized, so it does not occupy memory
  • SingleTonHoler does not need to be loaded when the SingleTon is first loaded. It is only when the getInstance() method is called for the first time that INSTANCE is used that the virtual machine loads the SingleTonHoler class.

So how do you achieve thread-safety?

In the final stage of class loading: class initialization, which essentially executes the < Clinit > method of the class constructor. < Clinit > is generated by the Javac compiler, and the JVM ensures that a class’s < Clinit > is locked and synchronized correctly in a multithreaded environment. Simply put, if multiple threads are initializing the class, only one thread will execute the < Clinit > method, and the other threads will block until the execution is complete. Other threads wake up, but do not execute the

method again. That is, a class is initialized only once.

As you can easily see from the singleton above, the assignment of INSTANCE is actually a < Clinit > code. When we execute getInstance(), it causes the SingletonHolder class to be loaded, and the class initialization is performed at the end of the loading. Even with multiple threads, < Clinit > is executed only once, so only one instance of it exists to avoid multithreading problems.

Idlers singleton

public class Singleton{ private static Singleton instance= null; private static Singleton(){} public static Singleton getInstance(){ if(instance==null){ instance = new Singleton(); } return instence; }}Copy the code
  • This mode, which initializes instances only when needed, works well with single threads, but has thread-safety issues with multiple threads.
  • Advantages: Saving resources
  • Disadvantages: the first load needs to be instantiated, the reaction is a little slow; Does not work properly in multithreading

Slacker + thread-safe singleton

public class Singleton{ private static Singleton instance =null; private static Singleton(){} public static synchronized getInstance(){ if(instance==null){ instance =new Singleton(); } return instance; }}Copy the code
  • In order to solve the multithreading problem, this mode adopts the method of synchronizing functions, but it is a waste of resources, because synchronization checks are performed every time, when the real check is only needed during the first instantiation.
  • Advantages: In multithreading can be used safely
  • Disadvantages: Unnecessary synchronization overhead

Enumerated the singleton

public enum Singleton{
    INSTANCE
}
Copy the code
  • It’s a model that almost no one uses, so just know.

Double check lock singleton (DCL)

public class Singleton{ private static volatile Singleton instance=null; private static Singleton(){} public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class){ if(instance==null){ instance=new Singleton(); } } } return instance; }}Copy the code
  • The first nullation is to reduce unnecessary synchronization overhead, but also an improvement on the above writing method; The second nullation is to create the instance object. Notice how it’s used herevolatileThe keyword.
  • This mode not only solves the problem of resource waste, but also solves the problem of multi-threading.
  • Advantages: High resource utilization and thread safety.
  • Disadvantages: slightly slow on first loading, defective in high concurrency environment.