1. Single case mode
What is singleton mode? In short, ensure that classes defined as singleton patterns have and only have one instance in the program. Features of single case mode:
-
Only one instance (only one object can be created)
-
Self instantiation (class constructor private)
-
Static methods for obtaining instances
2. Implementation of singleton mode
There are five common implementation methods of singleton mode:
2.1. Lazy
Lazy type (also known as satiated type), the specific code is as follows:
public class Singleton { /** * Self instantiation */ private static Singleton singleton; /** * Constructor private */ private Singleton() { System.out.println("Create a single instance..."); } /** * Static methods for obtaining instances */ public static Singleton getInstance() { if (null == singleton) { singleton = new Singleton(); } return singleton; } }
From the code implementation, it can be seen that the instance is not initialized at the beginning, but a single instance will be generated after calling the * * getInstance() *. This mode delays the initialization of the instance, but it is not thread safe.
public class SingleTonTest { /** * Testing whether lazy mode is thread safe in multithreading mode * * @param args */ public static void main(String[] args) { /** * It is convenient to use Executors to create thread pool * Alibaba development manual does not recommend this */ ExecutorService executorService = Executors.newFixedThreadPool(5); for (int i = 0; i < 20; i++) { executorService.execute(() -> System.out.println(Thread.currentThread().getName() + "::" + Singleton.getInstance())); } } }
Screenshot of test results:
Lazy type loads objects at run time, so loading the singleton class will be faster, but getting objects will be slower. If you want thread safety, you can add synchronized keyword to getInstance(), but it will cost us a lot of efficiency.
2.2. Hungry Han style
Creating instance objects in advance has high calling efficiency, but it can't delay loading, which is easy to generate garbage and thread safety.
public class Singleton { /** * Self instantiation */ private static Singleton singleton = new Singleton(); /** * Constructor private */ private Singleton() { System.out.println("Create a single instance..."); } /** * Static methods for obtaining instances */ public static Singleton getInstance() { return singleton; } }
2.3. Double check lock mode
public class Singleton { /** * Self instantiation, volatile decoration, ensuring visibility between threads */ private volatile static Singleton singleton; /** * Constructor private */ private Singleton() { System.out.println("Create a single instance..."); } /** * Static methods for obtaining instances */ public static Singleton getInstance() { // Check for the first time to avoid unnecessary instances if (singleton == null) { // Second check, synchronization, to avoid multithreading problems synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
Since the creation of singleton=new Singleton() object may be reordered in the JVM, there is a risk in multi-threaded access. Using volatile to modify the signleton instance variable can prohibit instruction reordering, make the object visible among multi threads, and effectively solve the problem.
The failure of double check locking is not due to implementation bug s in the JVM, but to the Java platform memory model. The memory model allows so-called "unordered writes," which is one of the main reasons these idioms fail
2.4. Static internal class mode
public class Singleton { /** * Constructor private */ private Singleton() { System.out.println("Create a single instance..."); } private static class SingletonInner { private static Singleton instance = new Singleton(); } private static Singleton getInstance() { return SingletonInner.singleton; } }
In this way, we make full use of the characteristics of static internal classes - initialization and external classes are separate. Only when the * * getInstance() * * method is called for the first time, the virtual machine will load the internal class (singletoniner. Class) and initialize the instance to ensure the uniqueness of the object.
2.5. Enumerate singleton mode
public enum Singleton { INSTANCE }
It feels very simple. The objects created by the default enumeration class are all singleton, and multi threading is supported.
3. Summary of single case mode
- The advantage of singleton mode is that only a single instance can be generated globally, so it can save system resources and reduce performance overhead. However, just because there is only a single instance, the responsibility of the single instance class is too heavy, which violates the * * single responsibility principle * *, and the single instance class has no abstract methods, which makes it difficult to expand.
- In all the above singleton modes, it is recommended to use the implementation of static inner class, which is very intuitive and ensures thread safety. Enumerations are recommended in Effective Java, but they are too simple, resulting in poor readability of the code.
- The singleton mode is a creation mode. When deserializing, you need to override the * * readremove() * * method to ensure that the instance is unique.
The article first appeared on my blog: www.develope.top, reprint please indicate the source!
Pay attention to the public address, back 666, receive benefits: