1. What is singleton mode
The so-called class singleton design pattern is to take certain methods to ensure that there can only be one instance object for a class in the whole software system, and the class only provides a method to obtain its object instance (static method)
2. Hungry Han formula (static variable)
1. Privatize the constructor to prevent external new
2. Create object instances within this class
3. Provide a public static method to return the instance object
class Test { public static void main(String[] args) { //Get instance object Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //Get as the same object System.out.println(instance == instance1); //true } } //Hungry Han formula (static variable) public class Singleton { //1. Privatize the constructor to prevent external 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; } }
- Advantages: this writing method is relatively simple. The instantiation is completed when the class is loaded, avoiding the problem of thread synchronization
- Disadvantages: instantiation is completed during class loading, which does not achieve the effect of Lazy Loading. If this instance has never been used from beginning to end, it will cause a waste of memory
- This method is based on the classloader mechanism to avoid the problem of multi-threaded synchronization. However, instance is instantiated when class is loaded. In singleton mode, most of them call getInstance method, but there are many reasons for class loading. Therefore, it is uncertain that other methods (or other static methods) cause class loading. At this time, initializing instance does not achieve the effect of Lazy Loading
3. Hungry Chinese style (static code block)
The advantages and disadvantages are the same as static variables
class Test { public static void main(String[] args) { //Get instance object Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //The singleton object obtained is the same object System.out.println(instance == instance1); //true } } //Hungry Chinese (static code block) public class Singleton { //1. Privatize the constructor to prevent external new private Singleton() { } //2. Create object instances within this class private static Singleton instance; //3. Create a singleton object when the static code block is executed static { instance = new Singleton(); } //4. Provide a public static method to return the instance object public static Singleton getInstance() { return instance; } }
4. Lazy (static variable)
1. Privatize the constructor to prevent external new
2. Create object instances within this class
3. Provide a public static method. It will be created only when this method is used
class Test { public static void main(String[] args) { //Get instance object Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //The singleton object obtained is the same object System.out.println(instance == instance1); //true } } //Lazy (static variable) public class Singleton { //1. Privatize the constructor to prevent external new private Singleton() { } //2. Create object instances within this class private static Singleton instance; //3. Provide a public static method. It will be created only when this method is used public static Singleton getInstance() { if(instance == null){ instance = new Singleton(); } return instance; } }
- Advantages: it plays the role of Lazy Loading, but it can only be used under single thread
- Disadvantages: if a thread enters the if(instance == null) {} judgment statement block under multithreading, there may be urgent execution in the future. If another thread also passes the judgment statement, multiple instances will be generated. Therefore, do not use this method under multithreading
- Conclusion: do not use this method in actual development
5. Lazy (thread safety, synchronization method)
class Test { public static void main(String[] args) { //Get instance object Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //The singleton object obtained is the same object System.out.println(instance == instance1); //true } } //Lazy (thread safety, synchronization method) public class Singleton { //1. Privatize the constructor to prevent external new private Singleton() { } //2. Create object instances within this class private static Singleton instance; //3. Provide a public static method and add the keyword synchronized, which is thread safe at this time public static synchronized Singleton getInstance() { if(instance == null){ instance = new Singleton(); } return instance; } }
- Advantages: it solves the problem of thread insecurity
- Disadvantages: the efficiency is too low. When each thread obtains an instance of this class, it needs to synchronize when executing the getInstance() method, and only one instantiation of this method is enough. For the later desired instance of this class, just return directly. The efficiency of method synchronization is too low
6. Double - check
class Test { public static void main(String[] args) { //Get instance object Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //The singleton object obtained is the same object System.out.println(instance == instance1); //true } } //Lazy (thread safety, synchronization method) public class Singleton { //1. Privatize the constructor to prevent external new private Singleton() { } //2. Create object instances within this class private static volatile Singleton instance; //3. Provide a public static method, add double check code, solve thread safety problems, and solve lazy loading at the same time public static synchronized Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
- The concept of Double - Check is often used in multithreading development. The if (instance == null) check is performed twice to ensure thread safety
- The instantiation code is executed only once. When accessing again later, judge if (instance == null) and return the instantiated object directly, which also avoids repeated method synchronization
- Thread safety; Delayed loading, high efficiency
7. Static internal class implementation
package com.wzj.singleton06; class Test { public static void main(String[] args) { //Get instance object Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); //The singleton object obtained is the same object System.out.println(instance == instance1); //true } } //Lazy (thread safety, synchronization method) public class Singleton { //1. Privatize the constructor to prevent external new private Singleton() { } //2. Create static inner class private static class Inner{ private static final Singleton INSTANCE = new Singleton(); } //3. Provide a public static method to obtain the properties in the static internal class and create an instance object public static Singleton getInstance() { return Inner.INSTANCE; } }
- Class loading mechanism is adopted to ensure that there is only one thread when initializing the instance
- In the static internal class mode, the Singleton class will not be instantiated immediately when it is loaded. Instead, when instantiation is required, the inner class will be loaded by calling the getInstance method, so as to complete the instantiation of Singleton
- 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
- Advantages: thread insecurity is avoided, delayed loading is realized by using the characteristics of static internal classes, and the efficiency is high
8. Enumeration implementation
class Test { public static void main(String[] args) { //Get instance object Singleton instance = Singleton.INSTANCE; Singleton instance1 = Singleton.INSTANCE; //The singleton object obtained is the same object System.out.println(instance == instance1); //true } } //Use enumeration to get singleton object enum Singleton{ INSTANCE; //attribute public void say(){ System.out.println("ojbk"); } }
- Catch jdk1 here 5 to implement the singleton object, which can not only avoid the problem of multi-threaded synchronization, but also prevent deserialization and re creation of new objects
9. Precautions for singleton mode
- The singleton mode ensures that there is only one object of this class in the system memory, which saves system resources. For some objects that need to be created and destroyed frequently, using the singleton mode can improve the system performance
- When you want to instantiate a singleton class, you must use the corresponding method to obtain the object, not new directly
- Scenarios for using singleton mode: objects that need to be created and destroyed frequently, objects that take too much time to create or destroy too many resources (i.e. heavyweight objects), but are often used, tool objects, and objects that frequently access databases or files (such as data sources, session factories, etc.)