Singleton mode

1. Concept diagram

Singleton design pattern definition: Ensures that there is only one instance of this class, and automatically instantiates this object to the system.

Sample code

package com.model.test;
public class Singleton {
	// Use static variables to record unique instances
	private static Singleton singleton = null;
	private Singleton (a){}
	public static Singleton getInstance (a){
		if (singleton == null){
			singleton = new Singleton() ;
		}
		return singleton ;
	}
	public static void main(String[] args) {
		Singleton singleton1 = Singleton.getInstance() ;
		Singleton singleton2 = Singleton.getInstance() ;
		/** * com.model.test.Singleton@15db9742 * com.model.test.Singleton@15db9742 */System.out.println(singleton1); System.out.println(singleton2); }}Copy the code

A Singleton is called a Singleton class, and the constructor uses a private modifier to ensure that only one instance can be generated in the system, and that it is generated automatically. The code above is lazy loading: it is created only when the object is used, meaning hungry to cook.

Second, thread safety

Thread A: Singleton == null thread A: singleton == null thread A: singleton == null thread A: singleton == null thread A: singleton == null So they all get an object instance, and that’s what’s called thread safety.

1. Synchronous control mode

package com.model.test;
public class Singleton {
	// Use static variables to record unique instances
	private static Singleton singleton = null;
	private Singleton (a){}
	public static synchronized Singleton getInstance (a){
		if (singleton == null){
			singleton = new Singleton() ;
		}
		returnsingleton ; }}Copy the code

This operation may affect system performance

2. Hungry loading

public class Singleton {
	// Use static variables to record unique instances
	private static Singleton singleton = new Singleton();
	private Singleton (a){}
	public static Singleton getInstance (a){
		returnsingleton ; }}Copy the code

Here to create the object, there is a need to use directly;

3. Double check

public class Singleton {
	// Use static variables to record unique instances
	// Volatile ensures that the singleton is initialized before multithreading can handle it correctly
	// The value of the variable that is volatile will not be cached by the local thread
	// All reads and writes to this variable operate directly on shared memory, ensuring that multiple threads handle the variable correctly.
	private static volatile Singleton singleton = null ;
	private Singleton (a){}
	public static Singleton getInstance (a){
		// If the instance does not exist, the synchronization zone is entered
		if (singleton == null) {// Only the first time will this code be fully executed
			synchronized (Singleton.class) {
				if (singleton == null){
					singleton = newSingleton() ; }}}returnsingleton ; }}Copy the code

4. Enumeration mode

package com.model.design.base.node01.singleton; import org.junit.Test; Public class C06_Singleton {@test public void C06_Singleton {@test public voidtest01 (){
 SingletonDemo INSTANCE1 = SingletonDemo.INSTANCE ;
 SingletonDemo INSTANCE2 = SingletonDemo.INSTANCE ;
 System.out.println(INSTANCE1 == INSTANCE2);
 INSTANCE1.info();
 INSTANCE2.info();
 }
}
enum SingletonDemo {
 INSTANCE ;
 public void info (){
 System.out.println("Implement singleton in enumeration mode"); }}Copy the code

Delay class initialization

1. Basic concepts

1) Class level inner class

To put it simply, a class-level inner class is a member inner class that has a static modifier. Member inner classes that are not static are called object-level inner classes. A class-level inner class is the static component of its outer class. Its objects have no dependencies on the outer class objects and can therefore be created directly. An instance of an object-level inner class is bound to an external object instance. In a class-level inner class, static methods can be defined. A static method can only refer to a static member method or a member variable in an external class. Class-level inner classes are members of their outer classes and are loaded only when they are first used.

2), multithreading default synchronization lock

In multithreading development, in order to solve the concurrency problem, synchronization is mainly used to add mutex for synchronization control. But in some cases, the JVM already implicitly performs synchronization, and in those cases you don’t have to do synchronization control on your own. These include:

    1. When initializing data by a static initializer (on a static field or in a static{} block)   2. Access final fields     3. When creating an object before creating a thread   4. When a thread can see the object it is about to processCopy the code

2. Implementation method

To achieve thread-safety easily, you can use a static initializer, which allows the JVM to keep threads safe. Type, such as in front of a starving man is implemented, at the time of class loading is initialized object, whether need or not, there is a certain space wasted. One possible approach is to use a class-level inner class in which object instances are created. In this way, as long as the class-level inner class is not used, no object instances are created, enabling both lazy loading and thread-safe.

public class LazySingleton {
	/** * Class level inner class */
	private static class SingletonHolder {
		private static LazySingleton lazySingleton = new LazySingleton() ;
	}
	public static LazySingleton getInstance (a){
		return SingletonHolder.lazySingleton ;
	}
	public static void main(String[] args) {
		LazySingleton lazySingleton1 = LazySingleton.getInstance() ;
		LazySingleton lazySingleton2 = LazySingleton.getInstance() ;
		/** * com.model.test.LazySingleton@15db9742 * com.model.test.LazySingleton@15db9742 */
		System.out.println(lazySingleton1+";"+lazySingleton2); }}Copy the code

JDK source singleton mode

Runtime singleton implementation source code.

1. Case demonstration

Public class C07_Singleton {public static void main(String[] args) {Runtime runtime1 = Runtime.getRuntime() ; Runtime runtime2 = Runtime.getRuntime() ; /* * 1229416514 * 1229416514 */ System.out.println(runtime1.hashCode()); System.out.println(runtime2.hashCode()); }}Copy the code

2. Source code analysis

public class Runtime {
 private static Runtime currentRuntime = new Runtime();
 public static Runtime getRuntime() {
 return currentRuntime;
 }
 private Runtime() {}}Copy the code

Singleton pattern based on Hanhan-hungry pattern.

5. Application in Spring framework

1. Create a test class

public class UserBean {}Copy the code

2. Spring configuration files

<! -- singleton Bean --> < Bean id="user" 
class="com.model.design.spring.node01.singleton.UserBean" />
Copy the code

3. Test reading Bean objects

package com.model.design.spring.node01.singleton;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/** * Spring framework singleton */
public class S01_Singleton {
    @Test
    public void test01 (a){
        ApplicationContext context01 = new ClassPathXmlApplicationContext("/spring/spring-context.xml");
        ApplicationContext context02 = new ClassPathXmlApplicationContext("/spring/spring-context.xml");
        UserBean user01 = (UserBean)context01.getBean("user"); UserBean user02 = (UserBean)context01.getBean("user"); UserBean user03 = (UserBean)context02.getBean("user");// com.model.design.spring.node01.singleton.UserBean@364841
        System.out.println(user01);
        // com.model.design.spring.node01.singleton.UserBean@364841
        System.out.println(user02);
        // com.model.design.spring.node01.singleton.UserBean@c4711cSystem.out.println(user03); }}Copy the code

Conclusion The main difference between the Spring singleton pattern and the pure singleton design pattern is that although the same classloader is used to load both application contexts, the UserBean instances are different. Singletons in the Spring framework are based on applications.

Summary of singleton pattern

1. Precautions

Singleton mode ensures that only one object of this class exists in the system memory, saving system resources. For some objects that need to be created and destroyed frequently, singleton mode can improve system performance. 2) When instantiating a singleton class, you must remember to use the corresponding method to get the Object, not the new Object() method. 3) Scenarios used by the singleton pattern: objects that need to be created and destroyed frequently, objects that take too much time or consume too much resources to create (i.e., heavyweight objects), but are often used.Copy the code

2. Advantages and disadvantages

Advantages: 1. Singleton mode creates only one object instance, reducing memory consumption 2. Set global access points to optimize access to shared resources disadvantages: 1Copy the code

Seven, source code address

Making address: given a smile cloud address: https://github.com/cicadasmile code laughed told https://gitee.com/cicadasmileCopy the code