The singleton pattern of java design optimization

  • 2020-05-05 11:20:36
  • OfStack

The singleton pattern is an object creation pattern that ensures that there is only one instance of a class in the system.

In java, this has two major benefits:

1. For frequently used objects, you can omit the time spent in creating the object;

2. As the number of new operations is reduced, the frequency of system memory is reduced, which reduces the pressure on GC and reduces the pause time of GC.

Singleton pattern segmentation:

1.


public class Singleton{
  private Singleton(){
    System.out.println("Singleton.Singleton()");
  }
  
  private static Singleton singleton = new Singleton();
  
  public static Singleton getInstance(){
    return singleton;
  }
}

Note: first, the singleton class must have an private access level constructor to ensure that the singleton is not instantiated by other code in the system. Second, the singleton member variable and the getInstance() method must be static.

This singleton class is simple to create and very reliable. The only disadvantage is that there is no way to lazily load singleton. For example, because the singleton creation process is very slow, because the member variable is defined as static, the singleton object will be created when jvm loads the singleton class, so the singleton object will be created wherever the singleton class is used, regardless of whether the singleton object is used or not. For example:


public class Singleton{
  private Singleton(){
    System.out.println("Singleton.Singleton()");
  }
  
  private static Singleton singleton = new Singleton();
  
  public static Singleton getInstance(){
    return singleton;
  }
  
  public static void createString(){
    System.out.println("Singleton.createString()");
  }
}

2. In order to improve the calling speed of related functions, lazy loading mechanism needs to be introduced.


package com.luchao.singtonle;

public class LazySingleton {
  private LazySingleton() {
    System.out.println("LazySingleton.LazySingleton()");
  }
  private static LazySingleton lazyInstance = null;
  
  public synchronized static LazySingleton getInstance(){
    if(lazyInstance==null)
      lazyInstance = new LazySingleton();
    return lazyInstance;
  }
}

For the static variable singleton, the initialization assignment is null, ensuring that there is no additional load when the system starts. In the getInstance() method, it determines that the current instance is very present, returns if it is, and builds the singleton if it is not. getInstance() must be a synchronous method, because in a multi-threaded environment, when thread 1 is building a singleton, thread 2 May judge instance to be null before completing the assignment, so thread 2 will start the program to create a new singleton, causing multiple singletons to be created.

The above example singleton implementation, while implementing lazy loading, introduces a synchronous approach that takes much longer in a multi-threaded environment than the first singleton.

3. The singleton pattern USES inner classes to maintain the creation of singletons


public class StaticSingleton {
  private StaticSingleton() {
    System.out.println("StaticSingleton.StaticSingleton()");
  }
  
  private static class SingletonHolder{
    private static StaticSingleton ataticSingleton = new     StaticSingleton();
  } 
  
  public static StaticSingleton getInstance(){
    return SingletonHolder.ataticSingleton;
  }
  
}

When StaticSingleton is loaded, the inner class is not instantiated, ensuring that the StaticSingleton class is not initialized when it is loaded into jvm, and that SingletonHolder is initialized when the getInstance() method is called. It is also used to build instances when the class is loaded, so it is inherently thread-friendly.

Using inner classes to complete the simple interest mode, which can achieve lazy loading, and also do not use the synchronization keyword, is a more perfect practice.

That's all for this article and I hope it will help you.


Related articles: