Singleton mode
Introduction to single example design 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 idea, and the class only provides a method to obtain its object instance (static method).
The singleton mode can be implemented in seven ways:
- Hungry Han formula (static constant)
- Hungry Chinese style (static code block) recommendation
- Lazy (thread unsafe)
- Lazy (thread unsafe, thread synchronization method)
- Double check recommendation
- Static internal class recommendation
- enumeration
Hungry Han formula (static constant)
Application example of hungry Han formula (static constant)
Steps:
- Constructor Privatization (prevent new)
- Class
- Expose a static public method
Code implementation:
public class SingletonTest01 { public static void main(String[] args) { //Get two Singleton objects Singleton singleton1 = Singleton.getSingleton(); Singleton singleton2 = Singleton.getSingleton(); //Output true to prove that the objects obtained twice are the same System.out.println(singleton1 == singleton2); System.out.println("singleton1.hashCode() = " + singleton1.hashCode()); System.out.println("singleton1.hashCode() = " + singleton2.hashCode()); } } class Singleton{ //1. Create object instances within this class private static final Singleton instance = new Singleton(); //2. The constructor is privatized and no external new is provided private Singleton(){} //3. Provide a common static method to return the instance object public static Singleton getSingleton(){ return instance; } }
Hungry Chinese style (static code block)
Description of advantages and disadvantages:
- Advantages: this method is very simple, that is, instantiation is completed when the class is loaded. Thread synchronization problems are avoided
- Disadvantages: the instantiation is completed when the class is loaded, which does not achieve the effect of Lazy Loading. If you have never used this instance from beginning to end, it will cause a waste of memory
- Conclusion: This singleton mode can be used on the premise that this class must be used at least once, otherwise it will cause a waste of memory.
Starving Han style (static code block) application case
public class SingletonTest02 { public static void main(String[] args) { //Get two Singleton objects Singleton02 singleton1 = Singleton02.getSingleton02(); Singleton02 singleton2 = Singleton02.getSingleton02(); //Get the object true twice, and the output is the same System.out.println(singleton1 == singleton2); System.out.println("singleton1.hashCode() = " + singleton1.hashCode()); System.out.println("singleton1.hashCode() = " + singleton2.hashCode()); } } class Singleton02 { private static Singleton02 instance; private Singleton02(){} static { //In a static code block, create a singleton object instance = new Singleton02(); } public static Singleton02 getSingleton02(){ return instance; } }
Lazy (thread unsafe)
Defect description:
- If this method is used in multithreading development, it will cause thread insecurity
- Reason: if thread A enters if and thread B grabs the thread execution right, then thread B will create an object, and thread A will also create an object when it comes back for execution
- Summary: in actual development, lazy singleton mode is not recommended
Lazy (thread unsafe) application examples:
public class SingletonTest03 { public static void main(String[] args) { //Get two Singleton objects Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); //Output true to prove that the objects obtained twice are the same System.out.println(singleton1 == singleton2); System.out.println("singleton1.hashCode() = " + singleton1.hashCode()); System.out.println("singleton1.hashCode() = " + singleton2.hashCode()); } } class Singleton{ private static Singleton instance; private Singleton(){} public static Singleton getInstance(){ if(instance == null){ instance = new Singleton(); } return instance; } }
Lazy (thread safe, synchronized code blocks)
Description of advantages and disadvantages:
- Advantages: thread safety, realizing the effect of lazy loading
- Disadvantages: when using multithreading, multiple threads want to get this object, and each time they need to wait for the previous thread
- Conclusion: this method is not recommended in actual development
Lazy (thread safety, synchronous code block) application examples:
public class SingletonTest04 { public static void main(String[] args) { //Get two Singleton objects Singleton04 singleton1 = Singleton04.getInstance(); Singleton04 singleton2 = Singleton04.getInstance(); //Output true to prove that the objects obtained twice are the same System.out.println(singleton1 == singleton2); System.out.println("singleton1.hashCode() = " + singleton1.hashCode()); System.out.println("singleton1.hashCode() = " + singleton2.hashCode()); } } class Singleton04{ private static Singleton04 instance; private Singleton04(){} /** * Add synchronous processing code to solve thread safety problems * But it's less efficient * @return */ public static synchronized Singleton04 getInstance(){ if(instance == null){ instance = new Singleton04(); } return instance; } }
duplication check
Description of advantages:
- This method is often used in development. In the following code, if is checked twice to ensure thread safety
- Advantages: thread safety, delayed loading (lazy loading) and high efficiency
- Conclusion: this single case design is recommended in practical development
Double check application example:
public class SingletonTest05 { public static void main(String[] args) { //Get two Singleton objects Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); //Output true to prove that the objects obtained twice are the same System.out.println(singleton1 == singleton2); System.out.println("singleton1.hashCode() = " + singleton1.hashCode()); System.out.println("singleton1.hashCode() = " + singleton2.hashCode()); } } class Singleton{ private static volatile Singleton instance; private Singleton(){} /** * Add double check code to solve the thread problem and lazy loading problem at the same time * At the same time, the efficiency is guaranteed * @return */ public static Singleton getInstance(){ if(instance == null){ synchronized (Singleton.class) { if(instance == null) { instance = new Singleton(); } } } return instance; } }
Static inner class
Description of advantages:
- This method adopts the mechanism of class loading to ensure that there is only one thread when initializing the instance.
- The static internal class method does not instantiate the Singleton class immediately when it is loaded, but calls the getInstance method when instantiation is needed to load the Singleton class, 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, so here, 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
- Conclusion: it is recommended to use
Static internal class application instance:
public class SingletonTest06 { public static void main(String[] args) { //Get two Singleton objects Singleton singleton1 = Singleton.getInstance(); Singleton singleton2 = Singleton.getInstance(); //Output true to prove that the objects obtained twice are the same System.out.println(singleton1 == singleton2); System.out.println("singleton1.hashCode() = " + singleton1.hashCode()); System.out.println("singleton1.hashCode() = " + singleton2.hashCode()); } } class Singleton{ private Singleton(){} //Write a static inner class with a static attribute Singleton private static class SingletonInstance{ private final static Singleton INSTANCE = new Singleton(); } //Provide a method to get common property and directly return singletoninstance INSTANCE public static Singleton getInstance(){ return SingletonInstance.INSTANCE; } }
enumeration
Description of advantages and disadvantages:
- With jdk1 5 to implement the singleton mode, which can not only avoid the problem of thread synchronization, but also prevent deserialization and re creation of new objects
- Summary: Recommended
Enumerate application instances:
public class SingletonTest07 { public static void main(String[] args) { Singleton instance1 = Singleton.INSTANCE; Singleton instance2 = Singleton.INSTANCE; System.out.println(instance1 == instance2); System.out.println(instance1.hashCode()); System.out.println(instance2.hashCode()); instance1.test(); } } enum Singleton{ INSTANCE; //attribute public void test(){ //method System.out.println("ok"); } }
Source code analysis of singleton mode in JDK application
In * * Java The Runtime under Lang package uses the singleton mode of hungry Han formula (static constant) * *
code:
public class Runtime { private static Runtime currentRuntime = new Runtime(); /** * Returns the runtime object associated with the current Java application. * Most of the methods of class <code>Runtime</code> are instance * methods and must be invoked with respect to the current runtime object. * * @return the <code>Runtime</code> object associated with the current * Java application. * */ public static Runtime getRuntime() { return currentRuntime; } /** Don't let anyone else instantiate this class */ private Runtime() {} //There are many ways }
Notes and details of singleton mode
- The singleton mode ensures that there is only one object in the system memory, which saves system resources. For some objects that need to be created and destroyed frequently, the singleton mode can improve the system performance
- When you want to instantiate a singleton class, you must remember to use the corresponding method to get the object instead of new
- Singleton usage scenarios: 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 database files (such as data sources, session factories, etc.)