Explore the singleton design pattern of java design pattern

Posted by jcd on Sun, 16 Jan 2022 09:49:25 +0100

Singleton design pattern

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 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.

There are eight ways of single instance design mode:
1) Hungry Han formula (static constant)
2) Hungry Chinese (static code block)
3) Lazy (thread unsafe)
4) Lazy (thread safety, synchronization method)
5) Lazy (thread safe, synchronous code block)
6) Double check (recommended)
7) Static inner class (recommended)
8) Enumeration (recommended)

1. Hungry Han formula (static constant) (it is also recommended when it is guaranteed to be used)
Application example of hungry Han formula (static constant)
The steps are as follows:

1) Constructor privatization (Prevent passage new Create an object and get the instance object of the class through the class name)
2) Create objects inside the class (with public static final Modifier, related to class and can be accessed directly through class)
3) Expose a static public method. getInstance
4) code implementation
package type1;

public class SingleTonDemo1 {
	public static void main(String[] args) {
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance==instance2);
	}

}

//Hungry Han formula (static constant)
class Singleton{
	//1. The constructor is privatized, and external objects cannot be created through construction methods
	private Singleton(){

	}

	//	2. Create an instance object inside this class, and create an object instance when the class is loaded
	private final static Singleton instance=new Singleton();

	//	3. Provide a public static method to return the instance object
	public static Singleton getInstance(){
		return instance;
	}
}

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 class loading mechanism and avoids the synchronization problem of multiple threads. 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 ways (or other static methods) to cause class loading. At this time, initializing instance does not achieve the effect of lazy loading
4) Conclusion: This singleton mode is available and may cause memory waste.

2. Hungry Chinese style (static code block)
In fact, it is similar to the above code, that is, the created instance object is placed in the static code block, and the class will be initialized as it is loaded.

package type2;

public class SingleTonDemo2 {
	public static void main(String[] args) {
		Singleton instance = Singleton.getInstance();
		Singleton instance2 = Singleton.getInstance();
		System.out.println(instance==instance2);
	}

}

//Hungry Chinese style (static code fast)
class Singleton{
	//1. The constructor is privatized, and external objects cannot be created through construction methods
	private Singleton(){

	}

	//	2. Create an instance object inside this class, and create an object instance when the class is loaded
	private static Singleton instance;

	static {
		instance=new Singleton();
	}

	//	3. Provide a public static method to return the instance object
	public static Singleton 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)
When the instance object is needed, the method is called for initialization to achieve the effect of lazy loading and make up for the shortcomings of hungry man.

Case analysis:

package type3;

public class SingleTonDemo3 {
	public static void main(String[] args) {
		SingleTon instance = SingleTon.getInstance();
		SingleTon instance2 = SingleTon.getInstance();
		System.out.println(instance==instance2);
	}
}

class SingleTon{
	private static SingleTon instance;
	private SingleTon() { }

	//	Provide a static common method. When this method is used, create an instance, that is, lazy
	public static  SingleTon getInstance(){
		if (instance==null){
			instance=new SingleTon();
		}
		return instance;
	}
}

Description of advantages and disadvantages:
1) It has the effect of lazy loading, but it can only be used under single thread.

Resolution:
If in multithreading, a thread enters if (singleton == null)Before the judgment statement block can be executed, another thread also passes the judgment statement. At this time, multiple instances will be generated. Therefore, this method cannot be used in multithreading environment, which is also a disadvantage of lazy thread unsafe writing.
  1. Conclusion: do not use this method in actual development.

4. Lazy (thread safety, synchronization method)
Different from the above thread unsafe writing method, the synchronized keyword is added to the getInstance() method to synchronize the code. When a thread comes in, other ready-made threads wait in line first. After the thread is called, other threads come in. This ensures that there is only one object in the system and that threads are mutually exclusive to access the synchronized code.

synchronized keyword can ensure that only one thread can execute the method or code block modified by it at any time.

Case:

package type4;


public class SingleTonDemo4 {
	public static void main(String[] args) {
		SingleTon instance = SingleTon.getInstance();
		SingleTon instance2 = SingleTon.getInstance();
		System.out.println(instance==instance2);
	}
}

class SingleTon{
	private static SingleTon instance;
	private SingleTon() { }

	//	A static common method is provided, and the code of synchronous processing is added to solve the problem of thread safety
	public static synchronized SingleTon getInstance(){
		if (instance==null){
			instance=new SingleTon();
		}
		return instance;
	}


}

Description of advantages and disadvantages:
1) The problem of thread safety 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)

This method is not recommended because it does not solve the problem of multithreading.

6. Double check (recommended)
1) Double checking is often used in multithreading development. As shown in the code, we have conducted two if (singleton == null) checks to ensure thread safety.
2) Through double checking, 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.

Implementation process: if there are three processes that need the instance, the first a and B processes arrive almost at the same time. If they are empty, they enter the first layer if. Because the instantiated code part adds synchronize to represent the synchronization code, this is that only one a and B can enter the synchronization code for the second layer if. If they are empty, they create an object, At this time, instance is added to the main memory. When the second process enters the synchronization code, it is no longer empty. return directly. When the third process enters the first layer if, it is not empty and can be returned directly.

7. Static inner class (recommended)

Implementation method:
1) This method adopts the mechanism of class loading to ensure that there is only one thread when initializing the instance.
2) The static inner class (SingletonInstance) will not be instantiated immediately when the Singleton class is loaded. 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. (when Singleton needs to be instantiated, getInstance () is called to load and initialize the static internal class)
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 (recommended)
Description of advantages and disadvantages:
1) With jdk1 5 to implement the singleton mode. It can not only avoid multi-threaded synchronization problems, but also prevent deserialization and re creation
New object.
2) This approach is advocated by Josh Bloch, author of Effective Java
3) Conclusion: it is recommended to use.

Source code analysis of singleton pattern in JDK application
In JDK, Java Lang. runtime is the classic singleton mode (hungry Chinese style)

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.)

Topics: Java Design Pattern