1. Introduction

  • Take measures to ensure that only one object instance of a class can exist in the entire software system, and that class provides only one method (static method) to obtain its object instance.
  • Ensure that only one instance can exist within a JVM, ensuring that objects are unique

2. Singleton mode

2.1 Hungry (static constant)

Basic steps

1) Privatize the constructor (to prevent new) 2) create objects inside the class 3) expose a static public method (getInstance)

Code implementation

class Singleton1 {
   // Private constructors are privatized
   private Singleton1(a) {}private final static Singleton1 instance = new Singleton1();

   public static Singleton1 getInstance(a) {
       returninstance; }}Copy the code

The advantages and disadvantages

1) Advantages: The writing method is relatively simple, that is, the instantiation is completed at the time of class loading, avoiding the thread synchronization problem. This method is based on the ClassLoader mechanism to avoid multithreaded synchronization problems. However, the instance is instantiated when the class is loaded. In singleton mode, the getInstance method is mostly called, but there are many reasons for class Loading, so it is not certain that there is another way (or another static method) to load the class (possibly creating objects synchronously), and then instance initialization is not Lazy

conclusion

This singleton pattern is available, but can be a memory waste

2.2 Hungry (Static Code Block)

Basic steps

1) Privatize the constructor (to prevent new) 2) create objects with static code blocks inside the class 3) expose a static public method (getInstance)

Code implementation

class Singleton2 {
   private static Singleton2 instance;

   // Private constructors are privatized
   private Singleton2(a) {}static {  // In a static code block, create a singleton object
       instance = new Singleton2();
   }

   public static Singleton2 getInstance(a) {
       returninstance; }}Copy the code

The advantages and disadvantages

1) This method is similar to the first method (static constant), except that the class instantiation process is placed in the static code block, and the code in the static code block is executed when the class is loaded, and the class instance 2 is initialized

conclusion

This singleton pattern is available, but can be a memory waste

2.3 Lazy (Threads are not safe)

Basic steps

1) Privatize the constructor (to prevent new) 2) instantiate the object only when the getInstance method is called 3) expose a static public method (getInstance)

Code implementation

class Singleton3 {
    private static Singleton3 instance;

    // Private constructors are privatized
    private Singleton3(a) {}public static Singleton3 getInstance(a) {
        if (instance == null) {
            instance = new Singleton3();
        }
        returninstance; }}Copy the code

The advantages and disadvantages

If (instance == null) {if (instance == null) {if (instance == null) {if (instance == null) { Therefore, this method cannot be used in multithreaded environments

Multithreaded unsafe code demonstration

  • code
    public class SingletonTest3 {
        public static void main(String[] args) {
            for (int i = 0; i < 5; i++) {
               newThread(() -> System.out.println(Singleton3.getInstance().hashCode())).start(); }}}class Singleton3 {
        private static Singleton3 instance;
    
        // Private constructors are privatized
        private Singleton3(a) {}public static Singleton3 getInstance(a) {
            if (instance == null) {
                instance = new Singleton3();
            }
            returninstance; }}Copy the code
  • The execution result
    544002391
    118531371
    930626000
    118531371
    118531371
    Copy the code

    The hash code of the created instance object is printed based on the execution result. If they are different, the created object can be judged to be different. Therefore, the instance object created in this method is unsafe for multi-threading

conclusion

In instance development, do not use this approach because it is not thread safe

2.4 Lazy (thread-safe, synchronous method)

Basic steps

1) Privatize the constructor (to prevent new) 2) instantiate the object only when the getInstance method is called 3) expose a static public method (getInstance) 4) add synchronized to getInstance, Ensure that when a thread executes the method, no other thread can execute the method

Code implementation

class Singleton4 {
    private static Singleton4 instance;

    // Private constructors are privatized
    private Singleton4(a) {}public static synchronized Singleton4 getInstance(a) {
        if (instance == null) {
            instance = new Singleton4();
        }
        returninstance; }}Copy the code

The advantages and disadvantages

2) The execution efficiency is too low. When each thread obtains an instance of the class, it needs to execute the getInstance() method for synchronization. In fact, this method only executes the instantiation code once

conclusion

Thread-safe, but method synchronization is inefficient

2.5 Lazy (thread unsafe, synchronized code blocks)

Basic steps

1) Privatize the constructor (to prevent new) 2) instantiate the object only when the getInstance method is called to get the object 3) expose a static public method (getInstance) 4) create an instance in the getInstance method and synchronize the code block

Code implementation

class Singleton5 {
    private static Singleton5 instance;

    // Private constructors are privatized
    private Singleton5(a) {}public static Singleton5 getInstance(a) {
        if (instance == null) {
            synchronized (Singleton5.class) {
                instance = newSingleton5(); }}returninstance; }}Copy the code

The advantages and disadvantages

If (instance == null) {if (instance == null) {if (instance == null) {if (instance == null) Another thread passes the statement, and multiple instances are created

conclusion

In instance development, do not use this approach because it is not thread safe

2.6 Double Check

Basic steps

1) Privatize the constructor (to prevent new) 2) instantiate the object only when the getInstance method is called 3) expose a static public method (getInstance) 4) create an instance in the getInstance method, synchronize the code block and check again after entering the synchronized code block, Instance is created

Code implementation

class Singleton6 {
    private static volatile Singleton6 instance;

    // Private constructors are privatized
    private Singleton6(a) {}public static Singleton6 getInstance(a) {
        if (instance == null) {
            synchronized (Singleton6.class) {
                if (instance == null){
                    instance = newSingleton6(); }}}returninstance; }}Copy the code

The advantages and disadvantages

If (instance==null); if(instance==null); if(instance==null); Return instance objects directly to avoid repeated method synchronization

conclusion

Thread safety, delay loading, high effect

2.7 Static inner Classes

Basic steps

1) Privatize the constructor (to prevent new) 2) create a static inner class in the class to hold the entity object 3) expose a static public method (getInstance) 4) Static inner class characteristics: when the external class is loaded, the static inner class is not loaded immediately; A call to getInstance() from an external class causes the static inner class to be loaded once

Code implementation

public class Singleton7 {

    // Private constructors are privatized
    private Singleton7(a) {}private static class Singleton7Instance {
        private static final Singleton7 INSTANCE = new Singleton7();
    }

    public static Singleton7 getInstance(a) {
        returnSingleton7Instance.INSTANCE; }}Copy the code

The advantages and disadvantages

2) Static inner class methods are not instantiated immediately when the Singleton class is installed. Instead, the SingletonInstance class is loaded when it needs to be instantiated by calling getInstance(). Thus accomplishes the instantiation 3) Singleton class static attributes will only in the class is loaded for the first time initialization, here: the JVM helps us make sure the safety of the thread, initialized in the class, other threads cannot enter 4) advantages: avoid the thread is unsafe, using the characteristics of the static inner class implement lazy loading, high efficiency

conclusion

Thread safety, using static internal class characteristics to achieve delay loading, high efficiency

2.8 the enumeration

Basic steps

1) Use enumerations to provide instances and implement methods

Code implementation

public enum Singleton8 {
    INSTANCE;

    public void method(a) {
        / / method}}Copy the code

The advantages and disadvantages

1) Implementing the singleton pattern with enumerations added in JDK1.5 not only avoids thread synchronization problems, but also prevents deserialization from recreating new objects. 2) This approach is advocated by Effective Java author Josh Bloch

conclusion

This not only avoids thread synchronization problems, but also prevents deserialization from recreating new objects

3. Details

1) the singleton pattern to ensure the system memory in the class there is only one object, saves system resources, for some need to frequently create destruction of the object, using a singleton pattern can improve the performance of the system (2) when to instantiate a singleton class, must use the corresponding access to the object’s methods, rather than use the new 3) singleton usage scenarios: Objects that need to be created and destroyed frequently, objects that take too much time or resources to create but are frequently used, utility class objects, objects that frequently access databases or files (databases, session factories)