Singleton pattern of java design pattern

  • 2020-06-07 04:34:18
  • OfStack

Singleton pattern of java design pattern

Preface:

In software development, there are always 1 object that we only need 1, such as thread pool (threadpool), cache (cache), dialog box, preferences, etc. These objects may cause some unnecessary trouble if they produce multiple instances, such as abnormal program behavior, overuse of resources, etc. The singleton pattern ensures that there are only one instance of a class and provides global access points. The following is a simple singleton class to explore how to implement the singleton pattern.


/**
 *  The classic singleton class 
 */
public class Singleton {
  //  Set to a static variable for recording Singleton The only 1 The instance 
  private static Singleton singleInstance;
  private Singleton(){
    //  The constructor is declared private, which can only be used in Singleton Class to call this constructor 
  }
  /*
   *  To obtain Singleton Object, if not already instantiated 1 Object and return the instance 
   */
  public static Singleton getInstance(){
    if (singleInstance == null) {
      singleInstance = new Singleton();
    }
    return singleInstance;
  }
  //  Other methods 
}

As you can see from the above example, the Singleton class manages the instantiation of the class itself and provides global access points, which are set to static getInstance() methods that return 1 instance when other classes want to use Singleton. The advantage of this singleton pattern is deferred instantiation. Simply put, deferred instantiation is deferred initialization, where the actual instance is created when the class needs it, rather than creating an instance when the class is first loaded. For example, some objects do not need to be used from the beginning of program 1, or they are not used during program execution. However, this example has one drawback, which is that threads are not safe enough. Because if there are multiple threads executing simultaneously to the getInstance() method and Singleton does not have an instance of new Singleton(), then the threads will all consider singleInstance to be null and will instantiate Singleton, producing multiple instances of Singleton, which is obviously not consistent with the original intention of the singleton pattern. The next thing you might want to do is improve it


public class SingletonA {
  private static SingletonA singletongA;
  private SingletonA(){

  }
  /*
   *  increase synchronized The keyword getSingletonA Method becomes a synchronous method 
   */
  public static synchronized SingletonA getInstanceA(){
    if (singletongA == null) {
      singletongA = new SingletonA();
    }
    return singletongA;
  }
  //  Other methods 
}

In this example, the addition of synchronized can make getInstanceA() a synchronized method, in which a thread has to wait for other threads to leave the method before entering the method, making it possible for only one thread to execute the method at the same time.

Can almost solve the problem, but want to know is synchronized methods will influence the efficiency of the program execution, in this case we just in order to solve the first executive getInstance in example 1 () method will not result in multiple instances, but this case but will cause every time for instance will be called getInstanceA synchronization () method, and after there have been instances of call synchronized would be burdensome, because we didn't have to worry about the singleton class will be to create a new instance again. So we need to make one more improvement.

Since the above mentioned deferred instantiation, it would be much easier if it were not used.


public class SingletonB {
  //  In the static initializer ( static initializen ) to ensure thread safety 
  private static SingletonB singletonB = new SingletonB();
  private SingletonB(){
    //  The constructor 
  }
  public static SingletonB getInstaceB(){
    //  It's already instantiated, so just use it 
    return singletonB;
  }
}

The above approach is to create an instance as soon as JVM loads the class, because JVM creates the instance before the thread accesses it, so the thread is safe. But this can be a waste of resources compared to deferred instantiation. And if such a large case will be the program initialization time is longer.

Is it possible to use lazy instantiation without making threads unsafe and increasing access efficiency? The next step is to double check the lock to improve 1.


/**
 *  Double lock singleton mode 
 */
public class SingletonC {
  private volatile static SingletonC singletonC;
  private SingletonC(){

  }
  public static SingletonC getInstanceC(){
    if (singletonC == null) {
      synchronized (SingletonC.class) {
        if (singletonC == null) {
          singletonC = new SingletonC();
        }
      }
    }
    return singletonC;
  }
}

The above example is first check instance, entering a synchronized block, if not into the synchronous block after check again, if still null will create an instance, thus singletonC = new SingletonC () will only perform one, and then call getInstanceC () because there are instances when returned directly, so in addition to the first call when they walk in sync, and then not as example 2 every time synchronization method. This reduces the time to execute getInstanceC(). You will notice that there is an volatile keyword that makes singletonC visible to all threads after it is initialized, and that multiple threads can properly handle the SingletonC variable. Note, however, that the volatile keyword can only be used after Java 5, which would invalidated this double check before this release.

When using singleton mode, if there are multiple class loaders (classloader), you need to specify your own class loader and specify 1 class loader. Because each classloader defines a namespace, different classloaders may load the same class, resulting in multiple instances of the singleton class being created.

Thank you for reading, I hope to help you, thank you for your support to this site!


Related articles: