What is singleton mode
Singleton Pattern is one of the simplest design patterns in Java. This type of design pattern is a creation pattern, which provides the best way to create objects.
The singleton 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 object, which can be accessed directly without instantiating the object of this class.
be careful:
1. There can only be one instance.
2. You must create your own unique instance.
3. This instance must be provided to all other objects.
Singleton mode features
1. Privatization construction method
2. Create an object of this class in the class
3. Provide a global static method to get the object
Singleton pattern classification
1. Hungry Han style
Description: thread safe, commonly used, but prone to garbage, because it is initialized at the beginning
Advantages: no locking, high execution efficiency
Disadvantages: class is initialized when loaded, wasting memory
example:
public class Singleton { private static Singleton instance = new Singleton(); private Singleton() {} public static Singleton getInstance() { return instance; } }
2. Lazy style
① Lazy: thread unsafe
This method is the most basic implementation. The biggest problem of this implementation is that it does not support multithreading. Because there is no lock synchronized, it is not a singleton mode in a strict sense and cannot work normally in multithreading
example:
public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
② Lazy: thread safe but inefficient
Description: this method has good delayed loading and can work in multithreading, but its efficiency is very low. In most cases, synchronization is not required
Advantages: initialize only after the first call to avoid memory waste
Disadvantages: a synchronized lock must be added to ensure single instance, but locking will affect efficiency
example:
public class Singleton { private static Singleton instance; private Singleton() {} public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } }
③ Lazy: thread safe and high performance
Thread safety and delayed initialization. This method adopts the double lock mechanism DCL (double checked locking), which is safe and can maintain high performance in the case of multiple threads
example:
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; } //In the double check mode, the judgment is made twice: //The first is to avoid unwanted instances, //The second time is to synchronize and avoid multithreading problems. //Since the creation of singleton=new Singleton() objects may be reordered in the JVM, there is a risk in multi-threaded access. Using volatile to modify the signleton instance variable is effective to solve this problem
There are two other methods to implement singleton mode
① Static inner class implementation singleton
This method can achieve the same effect as the double check lock method, but the implementation is simpler. When using deferred initialization for static domains, this should be used instead of double check locking. This method is only applicable to the static domain. The double check lock method can be used when the instance domain needs to delay initialization
This method uses the classloader mechanism to ensure that there is only one thread when initializing an instance. The difference between this method and the hungry man method is that as long as the Singleton class is loaded, the instance will be instantiated (without the lazy loading effect). This method is that the Singleton class is loaded, and the instance may not be initialized. Only when getInstance method is explicitly called, the Singleton class will be explicitly loaded to instantiate instance
example:
public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() {} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
② Enumeration implementation singleton
This is the best way to implement singleton mode. It is more concise, automatically supports serialization mechanism and absolutely prevents multiple instantiations.
This method is advocated by Josh Bloch, the author of Effective Java. It can not only avoid the problem of multi-threaded synchronization, but also automatically support the serialization mechanism to prevent deserialization, re create new objects, and absolutely prevent multiple instantiations
example:
public enum Singleton { INSTANCE; public Singleton getInstance() { return INSTANCE; } }
Complete enumeration implementation singleton
public class Person { //Privatized constructor private Person(){ } //Define a static enumeration class static enum SingletonEnum{ //Create an enumeration object that is inherently singleton INSTANCE; private Person person; //Constructor for privatizing enumerations private SingletonEnum(){ person = new Person(); } public Person getInstnce(){ return person; } } //Expose a static method to get the User object public static Person getInstance(){ return SingletonEnum.INSTANCE.getInstnce(); } }