There are eight single-case patterns
First: Hungry Han (static constant)
public class SingleTonTest01 { public static void main(String[] args) { //test SingleTon1 instance = SingleTon1.getInstance(); SingleTon1 instance2 = SingleTon1.getInstance(); System.out.println(instance==instance2);//true System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } //Hungry Han Style (Static Constant) class SingleTon1{ //1. The constructor is private and cannot be new externally private SingleTon1(){ } //2. Create object instances within this class private final static SingleTon1 instance = new SingleTon1(); //3. Provide a common static method to return an instance object public static SingleTon1 getInstance(){ return instance; } }
Advantages and disadvantages:
1.Advantage: This is a simple way to write, that is, instantiate the class when it is loaded, avoiding the problem of thread synchronization.
2.Disadvantages: Instantiation is done when the class is loaded, which does not have the effect of Lazy Loading. If this instance has not been used from beginning to end, it will result in a waste of memory
3. This classloder-based mechanism avoids the problem of multithreaded synchronization. However, instances are instantiated when classes are loaded, and most of them call the getInstance method in the singleton mode, but there are many reasons for class loading, so there is no other way to determine.(or any other static method) causes the class to load, and initializing instances does not have the effect of Lazy Loading
4. Conclusion: This single-case mode is available and may cause memory waste
Second: Hungry Han (static code block)
public class SingleTonTest01 { public static void main(String[] args) { //test SingleTon1 instance = SingleTon1.getInstance(); SingleTon1 instance2 = SingleTon1.getInstance(); System.out.println(instance==instance2);//true System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } //Hungry Han Style (Static Code Block) class SingleTon1{ //1. The constructor is private and cannot be new externally private SingleTon1(){ } //2. Create object instances within this class private static SingleTon1 instance; static { instance = new SingleTon1(); } //3. Provide a common static method to return an instance object public static SingleTon1 getInstance(){ return instance; } }
Advantages and disadvantages:
1. This is similar to the above except that the instantiation of a class is placed in a static block of code, and when the class is loaded, the code in the static block of code is executed to initialize an instance of the class. The advantages and disadvantages are the same as above.
2. Conclusion: This singleton mode is available, but may cause memory waste
Third: Lazy (thread insecure)
public class SingleTonTest01 { public static void main(String[] args) { //test SingleTon1 instance = SingleTon1.getInstance(); SingleTon1 instance2 = SingleTon1.getInstance(); System.out.println(instance==instance2);//true System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } //Lazy (thread insecure) class SingleTon1{ //1. Create object instances inside this class private static SingleTon1 instance; //2. The constructor is private and cannot be new externally private SingleTon1(){ } //3. Provide a static, common method for creating instance objects that are lazy when used public static SingleTon1 getInstance(){ if(instance == null){ instance = new SingleTon1(); } return instance; } }
Advantages and disadvantages:
1. Lazy Loading works, but can only be used under a single thread
2. If a thread enters an if(singleton == null) judgment statement block under multithreading, and has not yet had time to execute it down, and another thread passes the judgment statement, multiple instances will be generated. This is not possible in a multithreaded environment.
3. Conclusion: Do not use this mode in actual development
Fourth: Lazy (thread-safe, synchronization method)
public class SingleTonTest01 { public static void main(String[] args) { //test SingleTon1 instance = SingleTon1.getInstance(); SingleTon1 instance2 = SingleTon1.getInstance(); System.out.println(instance==instance2);//true System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } //Lazy (thread-safe, synchronization method) class SingleTon1{ //1. Create object instances inside this class private static SingleTon1 instance; //2. The constructor is private and cannot be new externally private SingleTon1(){ } //3. Provide a static, common method for addressing thread security issues by adding synchronized code public static synchronized SingleTon1 getInstance(){ if(instance == null){ instance = new SingleTon1(); } return instance; } }
Advantages and disadvantages:
1. Solve thread insecurity
2. It is too inefficient for each thread to synchronize the getInstance() method when it wants to get an instance of a class. In fact, it is sufficient for this method to execute instantiation code only once. To get this kind of instance later, Return wakes up directly and the method is too inefficient to synchronize
3. Summary: In actual development, this is not recommended
Fifth: Lazy (synchronous code block) is not really thread safe
public class SingleTonTest01 { public static void main(String[] args) { //test SingleTon1 instance = SingleTon1.getInstance(); SingleTon1 instance2 = SingleTon1.getInstance(); System.out.println(instance==instance2);//true System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } //Lazy (Thread Safe, Synchronize Code Blocks) class SingleTon1{ private static SingleTon1 instance; private SingleTon1(){ } public static SingleTon1 getInstance(){ if(instance == null){ synchronized (SingleTon1.class){ instance = new SingleTon1(); } } return instance; } }
Advantages and disadvantages:
1. This is intended to improve the fourth implementation because the previous synchronization method was too inefficient and resulted in instantiated blocks of code being synchronized
2. However, this synchronization does not work for thread synchronization. Consistent with the third implementation, adding a thread into the if(singleton==null) judgment block before it has time to go down and the other thread passes the judgment statement will result in multiple instances
3. Conclusion: This method cannot be used in actual development
Sixth kind: Double check
public class SingleTonTest01 { public static void main(String[] args) { //test SingleTon1 instance = SingleTon1.getInstance(); SingleTon1 instance2 = SingleTon1.getInstance(); System.out.println(instance==instance2);//true System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } //duplication check class SingleTon1{ private static volatile SingleTon1 instance; private SingleTon1(){ } //Provides a static common method with double-checked code to solve thread security and lazy loading public static SingleTon1 getInstance(){ if(instance == null){ synchronized (SingleTon1.class){ if(instance == null){ instance = new SingleTon1(); } } } return instance; } }
Advantages and disadvantages:
1. The Double-Check concept is commonly used in multi-threaded development. As shown in the code, we checked if(instance == null) twice to ensure thread safety.
2. This way, the instantiation code is executed only once, and when accessed again later, if(instance == null) is judged, the object is instantiated directly by Return, and method synchronization is avoided repeatedly
3. Thread security, delayed loading, high efficiency
4. Conclusion: This singleton design pattern is recommended for practical development.
Seventh: Static Internal Class
public class SingleTonTest01 { public static void main(String[] args) { //test SingleTon1 instance = SingleTon1.getInstance(); SingleTon1 instance2 = SingleTon1.getInstance(); System.out.println(instance==instance2);//true System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } //Static Internal Class class SingleTon1{ private static volatile SingleTon1 instance; //Constructor Privatization private SingleTon1(){ } //Write a static internal class with a static property Singleton private static class SingletonInstance{ private static final SingleTon1 INSTANCE = new SingleTon1(); } //Provides a static common method that returns SingletonInstance.INSTANCE directly public static SingleTon1 getInstance(){ return SingletonInstance.INSTANCE; } //Description 1. The static internal class SingletonInstance will not be loaded when the class is loaded by SingleTon1 //2. When the getInstance method is called, the static internal class SingletonInstance performs class loading, which is thread-safe }
Explanation of advantages and disadvantages:
1. This approach uses a class loading mechanism to ensure that there is only one thread initializing the instance
2. Static internal class methods are not instantiated immediately when the SingleTon1 class is loaded. Instead, when instantiation is required, call the getInstance method to load the SingletonInstance class to complete the instantiation of Singleton
3. Class static properties are only initialized when the class is first loaded, so here, the JVM helps us keep threads safe, and no other threads can enter when the class is initialized
4. Advantages: Avoid thread insecurity, use static internal class feature to achieve delayed loading, high efficiency
5. Conclusion: Introduction and use
Eighth: Enumeration
public class SingleTonTest01 { public static void main(String[] args) { //test Singleton instance = Singleton.INSTANCE; Singleton instance2 = Singleton.INSTANCE; System.out.println(instance == instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); instance.sayOK(); } } //enumeration enum Singleton{ INSTANCE;//attribute public void sayOK(){ System.out.println("ok~"); } }
Advantages and disadvantages:
1. This implements the singleton mode with the help of enumerations added in JDK1.5, which not only avoids multithreaded synchronization problems, but also prevents deserialization from re-creating new objects
2. This approach is advocated by Effeetive Java author Josh Bloch
3. Promotional Use