Singleton mode
The so-called class singleton design pattern is to take certain methods to ensure that there can only be one object instance for a class in the whole software system, and the class only provides a method to obtain its object instance (static method).
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.
1. Hungry Han formula (static constant)
//Hungry Han formula (static variable) class Singleton01 { //1. Privatization of constructor private Singleton01() { } //2. Create object instances within this class private final static Singleton01 instance = new Singleton01(); //3. Provide a public static method to return the instance object public static Singleton01 getInstance() { return instance; } }
Description of advantages and disadvantages:
1) Advantages: this method is relatively simple, that is, the instantiation is completed when the class is loaded. It avoids the problem of thread synchronization.
2) Disadvantages: instantiation is completed when the class is loaded, 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
3) This method is based on the classloder mechanism and avoids the problem of multi-threaded synchronization. However, instance is instantiated when the class is loaded. In the singleton mode, most of them call the getInstance method. However, there are many reasons for class loading, so it is uncertain that there are other methods (or other static methods) This causes class loading. At this time, initializing instance does not achieve the effect of lazy loading
4) Conclusion: This singleton mode is available, which may cause a waste of memory
2. Hungry Chinese style (static code block)
//Hungry Chinese (static code block) class Singleton02 { //1. Privatization of constructor private Singleton02() { } //2. Create object instances within this class private static Singleton02 instance; //Creating singleton objects in static code blocks static { instance = new Singleton02(); } //3. Provide a public static method to return the instance object public static Singleton02 getInstance() { return instance; } }
Description of advantages and disadvantages:
1) This method is actually similar to the above method, except that the class instantiation process is placed in the static code block. When the class is loaded, the code in the static code block is executed to initialize the class instance. The advantages and disadvantages are the same as above.
2) Conclusion: This singleton mode is available, but it may cause memory waste
3. Lazy (thread unsafe)
//Thread unsafe lazy class Singleton03 { private static Singleton03 singleton; private Singleton03() { } //When getInstance is called, a singleton object is created, which is lazy public static Singleton03 getInstance() { if (singleton == null) { singleton = new Singleton03(); } return singleton; } }
Description of advantages and disadvantages:
1) It has the effect of Lazy Loading, but it can only be used under single thread.
2) If, under multithreading, one thread enters the if (singleton == null) 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)
//Lazy (thread safety, synchronization method) class Singleton04 { private static Singleton04 singleton; private Singleton04() { } //Added synchronization code to solve thread insecurity public static synchronized Singleton04 getInstance() { if (singleton == null) { singleton = new Singleton04(); } return singleton; } }
Description of advantages and disadvantages:
1) The thread unsafe problem is solved
2) The efficiency is too low. When each thread wants to obtain an instance of a class, it must synchronize the getInstance() method. In fact, this method only executes the instantiation code once. If you want to obtain this class instance later, just return it directly. Method is too inefficient to synchronize
3) Conclusion: this method is not recommended in practical development
5. Lazy (thread safe, synchronous code block)
//Lazy (thread safe, synchronous code block) class Singleton05 { private static Singleton05 singleton; private Singleton05() { } public static Singleton05 getInstance() { if (singleton == null) { synchronized (Singleton05.class) { singleton = new Singleton05(); } } return singleton; } }
Description of advantages and disadvantages:
1) This method is intended to improve the fourth implementation method because the previous synchronization method is too inefficient. Instead, it synchronizes to generate instantiated code blocks. 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 == null) judgment statement block and has not had time to execute, another thread also passes the judgment statement, multiple instances will be generated
3) Conclusion: this method cannot be used in practical development
6. Double check
//duplication check class Singleton06 { private static volatile Singleton06 singleton; private Singleton06() { } public static Singleton06 getInstance() { if (singleton == null) { synchronized (Singleton06.class) { if (singleton == null) { singleton = new Singleton06(); } } } return singleton; } }
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
7. Static internal class
//Static inner class class Singleton07 { private Singleton07() { } private static class SingletonInstance { private static final Singleton07 INSTANCE = new Singleton07(); } public static Singleton07 getInstance() { return SingletonInstance.INSTANCE; } }
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 getlnstance 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
5) Conclusion: it is recommended to use
8. Enumeration
//Enumeration implementation enum Singleton08 { INSTANCE; public void method() { System.out.println("Called method method"); } }
Description of 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: it is recommended to use
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) Scenarios for using singleton mode: objects that need to be created and destroyed frequently, objects that take too much time or resources to create objects (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.)