Welcome to follow the official wechat account: FSA Full Stack Action 👋

One, singleton pattern introduction

The singleton pattern can ensure that only one object instance is applied to the class in the system.

  • Benefits:

    • Save memory (no need to have multiple objects with the same function)
    • Improved performance (some objects are expensive to create)
  • Classification:

    • Han: Create the object in advance (classCreated as soon as it loads)
    • Lazy: Delay object creation (callgetInstance()When)
  • Implementation steps:

    • Private constructor
    • Provides methods to obtain singletons

Two, singleton pattern code implementation

1, hungry han type

  • Hunky way: Create the object in advance
  • Advantages: Simple implementation, no multithreaded synchronization issues
  • Disadvantages: The class is created as soon as it is loaded, and the instance object occupies memory whether it is used or not
/** * Single mode: Hunhun-style **@author GitLqr
 */
public class SingletonHungry {

	private static SingletonHungry instance = new SingletonHungry();

	private SingletonHungry(a) {}public static SingletonHungry getInstanceHungry(a) {
		returninstance; }}Copy the code

2, lazy

  • Lazy mode: delay object creation
  • Advantages: Objects are created only when they are needed, avoiding unnecessary memory waste
  • Cons: Multithreaded synchronization issues may need to be considered

1) DCL (+ volatile)

DCL, or double-checked Locking

  • synchronizedFirst null: avoids unnecessary lock synchronization and improves performance
  • synchronizedAfter the second sentence empty: avoid multithreaded security issues
  • volatileDecorated instance: avoids instruction reordering problems
/** * Singleton mode: DCL + volatile **@author GitLqr
 */
public class SingletonLazy {

	private static volatile SingletonLazy instance;

	private SingletonLazy(a) {}public static SingletonLazy getInstance(a) {
		if (instance == null) {
			synchronized (SingletonLazy.class) {
				if (instance == null) {
					instance = newSingletonLazy(); }}}returninstance; }}Copy the code

2) Static inner class mode

  • HolderStatic inner class: When an external class is loaded, it does not directly cause the static inner class to be loaded when calledgetInstance()When the static inner class is loaded, the execution can be delayed.
  • Holder.instanceStatic field: a type is initialized only once under the same loader, so it is naturally thread-safe.
/** * Singleton mode: lazyhead (static inner class) **@author GitLqr
 */
public class SingletonLazyClass {

	private static class Holder {
		private static SingletonLazyClass instance = new SingletonLazyClass();
	}

	public static SingletonLazyClass getInstance(a) {
		return Holder.instance;
	}

	private SingletonLazyClass(a) {}}Copy the code

Note: Static inner class is much simpler than DCL code, which has the advantage of han-style, and can do delayed initialization. It seems perfect, but it has a fatal problem, that is, it cannot pass parameters. Therefore, in the actual development, one of the implementation methods should be selected according to the actual situation.

3) Enumeration method

  • Enumerations cannot be new, so there is no need to privatize the constructor, which is much cleaner than the static inner class approach
  • Enumeration instance creation is thread safe
/** * Singleton mode: lazyhead (enumeration) **@author GitLqr
 */
public enum SingletonEnum {
	INSTANCE;

    // Enumerations can have fields and methods, just like normal classes
	public void method(a) {
		// TODO}}Copy the code

Note: The drawback is that, as with the static inner class approach, no external arguments can be passed.

Evolution of the DCL singleton pattern

Phase 1: Simple object nullity

  • Disadvantages: Thread unsafe, multi-threaded security issues
  • Solution: Lock
public class SingletonLazy {

	private static SingletonLazy instance;

	private SingletonLazy(a) {}public static SingletonLazy getInstance(a) {
		if (instance == null) {
			instance = new SingletonLazy();
		}
		returninstance; }}Copy the code

Phase 2: Synchronized guarantees singletons

  • Disadvantages: Locking methods with synchronized has a significant performance overhead
  • Solution: The lock size is not so large
public class SingletonLazy {

	private static SingletonLazy instance;

	private SingletonLazy(a) {}public static synchronized SingletonLazy getInstance(a) {
		if (instance == null) {
			instance = new SingletonLazy();
		}
		returninstance; }}Copy the code

Phase 3: DOUBLE-checked Locking of DCL

  • Advantages: High performance in multithreaded situations
  • Disadvantages: unsafe, instance = new SingletonLazy(); Not atomic, this line of code has the following three steps:
    1. Allocating memory space
    2. Creates objects in space
    3. Assign a value to a reference to an object
  • The reason: Because of the JVM reorder problem, it is possible that the thread will execute in the order 1->3->2 (the JVM thinks that 2 and 3 have no order), where step 3 will write the value in the thread side memory to the main memory, and the other thread will read the latest value in the instance. However, since step 2 has not been executed, the instance is an incomplete object, and other threads will fail to use the incomplete instance.
  • Solution: Use the volatile keyword
public class SingletonLazy {

	private static SingletonLazy instance;

	private SingletonLazy(a) {}public static SingletonLazy getInstance(a) {
		if (instance == null) {
			synchronized (SingletonLazy.class) {
				if (instance == null) {
					instance = newSingletonLazy(); }}}returninstance; }}Copy the code

Stage 4: DCL + volatile

  • Volatile: A keyword provided by Java that disallows reordering of instructions
public class SingletonLazy {

	private static volatile SingletonLazy instance;

	private SingletonLazy(a) {}public static SingletonLazy getInstance(a) {
		if (instance == null) {
			synchronized (SingletonLazy.class) {
				if (instance == null) {
					instance = newSingletonLazy(); }}}returninstance; }}Copy the code

If this article has been helpful to you, please feel free to follow my wechat official account: FSA Full Stack Action, which will be the biggest incentive for me. The public account not only has Android technology, iOS, Python and other articles, there may be skills you want to know oh ~