catalogue
Introduction to singleton mode:
There are eight ways of singleton design mode:
1. Hungry Han formula (static constant)
2. Hungry Chinese (static code block)
4. Lazy (thread safety, synchronization method)
5. Lazy (thread safe, synchronous code block)
7. Static inner class (recommended)
Source code analysis of singleton pattern in JDK application
Notes and details of singleton mode
Introduction to 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.
This 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.
For example, Hibernate's SessionFactory acts as a proxy for the data storage source and is responsible for creating the Session object. SessionFactory is not lightweight. Generally, only one SessionFactory is required for a project, which will use the singleton mode.
Advantages of singleton mode:
- Since it has only one object instance in memory, memory space is saved
- It can avoid frequent creation and destruction of objects and improve performance
- Avoid multiple occupation of shared resources and simplify access operations. For example, when writing files, because there is only one instance object, it can avoid writing to the same resource at the same time
- Provide a global access point for the whole system to optimize and share resource access.
Application scenario:
The core of singleton mode is to create only one instance in the whole system. Its application scenarios are mainly as follows:
1. Objects that take too much time or resources to create but are often used.
2. Objects that need to be instantiated frequently and then destroyed. Such as multi-threaded thread pool, network connection pool, etc.
3. When objects need to be shared. Since singleton mode allows only one object to be created, sharing the object can save memory and speed up object access. Such as the configuration object in the Web, the connection pool of the database, etc.
4. For some classes that need to be created frequently, using singleton can reduce the memory pressure of the system and reduce GC.
5. Counter of website (otherwise it is difficult to synchronize)
6.Windows Task Manager and recycle bin.
There are eight ways of singleton design mode:
1. Hungry Han formula (static constant)
Application example:
1. Privatization of constructor (prevent new)
2. Create objects inside the class
3. Expose a static public method: getInstance
4. Code implementation
public class SingletonTest01 { public static void main(String[] args) { //test Singleton instance1 = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance1=instance1); //true System.out.println("instance1.hsashCode="+instance1.hashCode()); System.out.println("instance2.hsashCode="+instance2.hashCode()); } } //Hungry Han style is hungry as the name suggests, so you should create objects from the beginning class Singleton{ // 1. The constructor is privatized, and the external cannot be new private Singleton(){ } // 2. Create object instances within this class private final static Singleton instance=new Singleton(); // 3. Provide a public static method to return the instance object public static Singleton getInstance(){ return instance; } }
Operation results:
Description of advantages and disadvantages:
1. Advantages: this method is relatively simple, that is, instantiation is completed when the class is loaded. Thread synchronization problems are avoided.
2. Disadvantages: the instantiation is completed when the class is loaded, which does not achieve the effect of Lazy Loading. If this instance is never used from beginning to end, it will cause a waste of memory
3. This method is based on the classloder mechanism to avoid the problem of multi-threaded synchronization. However, instance is instantiated during class loading. In the singleton mode, most of them call the getInstance method, but there are many reasons for class loading, so it is uncertain that there are other methods (or other static methods) cause class loading. At this time, initializing instance does not achieve the effect of lazy loading
Conclusion: This singleton mode is available, but it may cause memory waste
2. Hungry Chinese (static code block)
class Singleton01{ // 1. The constructor is privatized, and the external cannot be new private Singleton01(){ } // 2. Create object instances within this class private static Singleton01 instance; static { //In a static code block, create a singleton object instance=new Singleton01(); } // 3. Provide a public static method to return the instance object public static Singleton01 getInstance(){ return instance; } }
Advantages and disadvantages: like the above, this method is actually similar to the above method, except that the class instantiation process is placed in the static code block, that is, when the class is loaded, the code in the static code block is executed to initialize the class instance.
3. Lazy (thread unsafe)
public class SingletonTest03 { public static void main(String[] args) { //test System.out.println("Lazy, thread unsafe~"); Singleton03 instance1 = Singleton03.getInstance(); Singleton03 instance2 = Singleton03.getInstance(); System.out.println(instance1==instance2); //true System.out.println("instance1.hsashCode="+instance1.hashCode()); System.out.println("instance2.hsashCode="+instance2.hashCode()); } } //As the name suggests, the lazy type is lazy. It will not create objects just like the hungry type, but will be created when needed, and only once class Singleton03{ // 1. The constructor is privatized, and the external cannot be new private Singleton03(){ } // 2. Create object instances within this class private static Singleton03 instance; // 3. Provide a public static method. When this method is used, instance will be created //Lazy style public static Singleton03 getInstance(){ if(instance==null){ instance=new Singleton03(); } return instance; } }
Operation results:
Description of advantages and disadvantages:
1. It has the effect of Lazy Loading, but it can only be used under single thread.
2. If a thread enters the if (singleton == mull) judgment statement block and has not yet had time to execute, and another thread also passes the judgment statement, multiple instances will be generated. Therefore, this method cannot be used in a multithreaded environment
3. Conclusion: do not use this method in actual development
4. Lazy (thread safety, synchronization method)
class Singleton04{ // 1. The constructor is privatized, and the external cannot be new private Singleton04(){ } // 2. Create object instances within this class private static Singleton04 instance; // 3. Provide a public static method and add synchronous processing code to solve thread safety problems //Lazy style public static synchronized Singleton04 getInstance(){ if(instance==null){ instance=new Singleton04(); } return instance; } }
Operation results:
Description of advantages and disadvantages:
1. Solves thread safety issues
2. The efficiency is too low. When each thread wants to obtain an instance of a class, it needs to synchronize by executing the getInstance() method. In fact, this method only executes the instantiation code once, and the later ones just return if they want to obtain an instance of the class. The efficiency of method synchronization is too low
3. Conclusion: this method is not recommended in practical development
5. Lazy (thread safe, synchronous code block)
class Singleton05{ // 1. The constructor is privatized, and the external cannot be new private Singleton05(){ } // 2. Create object instances within this class private static Singleton05 instance; // 3. Provide a public static method and add synchronous code blocks public static Singleton05 getInstance(){ if(instance==null){ synchronized (Singleton05.class){ instance=new Singleton05(); } } return instance; } }
Description of advantages and disadvantages:
1. This method is intended to improve the fourth implementation method. Because the efficiency of the previous synchronization method is too low, the instantiated code block is generated synchronously
2. However, this synchronization does not play the role of thread synchronization. Consistent with the situation encountered in the third implementation method, if a thread enters the if (singleton == nul) judgment statement block and has not had time to execute down, another thread also passes the judgment statement, multiple instances will be generated
Conclusion: this method cannot be used in practical development
6. Double check (recommended)
//duplication check class Singleton06{ // 1. The constructor is privatized, and the external cannot be new private Singleton06(){ } // 2. Create object instances within this class private static volatile Singleton06 instance; // 3. Provide a public static method and add double check code to solve the thread safety problem and lazy loading problem public static synchronized Singleton06 getInstance(){ if(instance==null){ synchronized (Singleton06.class){ if(instance==null){ instance=new Singleton06(); } } } return instance; } }
Operation results:
Description of advantages and disadvantages:
1. The concept of double check is often used in multithreading development. As shown in the code, we have conducted two if (singleton==- null) checks to ensure thread safety.
2. In this way, the instantiated code is executed only once. When accessing again later, judge if (singleton ==null) and return the instantiated object directly to avoid repeated method synchronization
3. Thread safety; Delayed loading; High efficiency
4. Conclusion: this single case design pattern is recommended in practical development
Why must volatile be used?
In the java memory model, the volatile keyword is used to:
- Ensure memory visibility of variable operations by different threads
- Prohibit instruction reordering
7. Static inner class (recommended)
//The static internal class is completed, which is recommended class Singleton07{ // 1. Privatization of constructor private Singleton07(){ } // 2. Create object instances within this class private static volatile Singleton07 instance; //Write an internal static class that has a static property private static class SingletonInstance{ private static final Singleton07 INSTANCE=new Singleton07(); } // 3. Provide a public static method to directly return SingletonInstance.INSTANCE public static synchronized Singleton07 getInstance(){ return SingletonInstance.INSTANCE; } }
Operation results:
Description of advantages and disadvantages:
1. This method adopts the mechanism of class loading to ensure that there is only one thread when initializing the instance.
2. The static internal class method will not be instantiated immediately when the Singleton class is loaded. Instead, when instantiation is required, the SingletonInstance class will be loaded by calling the getInstance method, so as to complete the instantiation of Singleton.
3. The static properties of the class will only be initialized when the class is loaded for the first time. Therefore, the JVM helps us ensure the safety of threads. When the class is initialized, other threads cannot enter.
4. Advantages: thread insecurity is avoided, delayed loading is realized by using the characteristics of static internal classes, and the efficiency is high
8. Enumeration (recommended)
public class SingletonTest08 { public static void main(String[] args) { Singleton08 instance = Singleton08.INSTANCE; Singleton08 instance2 = Singleton08.INSTANCE; System.out.println(instance==instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); instance.sayOk(); } } //Using enumeration, you can implement singleton. It is recommended enum Singleton08{ INSTANCE;//attribute public void sayOk(){ System.out.println("ok~"); } }
Operation results:
Advantages and disadvantages:
1. This implements the singleton pattern with the help of enumerations added in JDK 1.5. It can not only avoid the problem of multi-threaded synchronization, but also prevent deserialization and re creation of new objects.
2. This approach is advocated by Josh Bloch, author of Effective Java
3. Conclusion: Recommended
Source code analysis of singleton pattern in JDK application
In our JDK, java.lang.Runtime is a classic singleton pattern (hungry Chinese)
As can be seen from the following source code:
Notes and details of singleton mode
1. The singleton mode ensures that there is only one object of this class in the system memory, saving system resources. For some objects that need to be created and destroyed frequently, using the singleton mode can improve the system performance
2. When you want to instantiate a singleton class, you must remember to use the corresponding method to get the object, not new
3. It is not recommended to use reflection to design singleton mode, because reflection can violently destroy singleton mode