Details of the singleton pattern in Java

  • 2020-05-16 07:01:31
  • OfStack

Singleton pattern concept:

The singleton mode in java is a common design mode. There are three types of singleton modes: lazy singleton, hungry singleton, and registered singleton.

The singleton pattern has the following characteristics:

1. The singleton class can only have one instance.

2. The singleton class must create its own unique instance.

3. The singleton class must provide this instance to all other objects.

The singleton pattern ensures that a class has only one instance and that it instantiates itself and provides that instance to the entire system. In computer systems, thread pools, caches, log objects, dialog boxes, printers, graphics card driver objects are often designed as singletons. All of these applications are more or less a resource manager. Each computer can have several printers, but only one Printer Spooler, to avoid having two print jobs output to the printer at the same time. Each computer can have a number of communication ports, which should be centrally managed so that one communication port is not simultaneously invoked by two requests. In short, the choice of singleton mode is to avoid the state, to avoid the government out of long.

Let's start with a classic singleton implementation.


public class Singleton {
  private static Singleton uniqueInstance = null;
 
  private Singleton() {
    // Exists only to defeat instantiation.
  }
 
  public static Singleton getInstance() {
    if (uniqueInstance == null) {
      uniqueInstance = new Singleton();
    }
    return uniqueInstance;
  }
  // Other methods...
}

Singleton avoids external instantiation of the class by restricting the constructor to private, and the only instance of Singleton within the same virtual machine can only be accessed through the getInstance() method. (in fact, it is possible to instantiate a class whose constructor is private through the Java reflection mechanism, which essentially invalidates all Java singletons. This issue will not be discussed here, let's pretend that the reflex mechanism does not exist.

But the above implementation does not consider thread safety. Thread safety is the idea that if your code is in a process where multiple threads are running at the same time, those threads might be running the code at the same time. If the result of each run is the same as that of a single thread, and the value of other variables is the same as expected, it is thread-safe. In other words, the interface provided by a class or program is an atomic operation for a thread, or switching between multiple threads will not result in the ambiguity of the execution result of the interface, that is, we do not have to consider the synchronization problem. Obviously, the above implementation does not meet the thread-safe requirements, and multiple instances of Singleton are likely to occur in a concurrent environment.


public class TestStream {
   private String name;
   public String getName() {
     return name;
   }
   public void setName(String name) {
     this.name = name;
   } 
   // This class can only have 1 An instance 
   private TestStream(){}  // Private no-argument constructor 
   // The class must be created itself 
   // There are 2 Kind of way 
   /*private static final TestStream ts=new TestStream();*/
   private static TestStream ts1=null;
   // This class must automatically provide this instance object to the entire system 
   public static TestStream getTest(){
     if(ts1==null){
       ts1=new TestStream();
     }
    return ts1;
   }
   public void getInfo(){
     System.out.println("output message "+name);
   }
 }

 public class TestMain {
   public static void main(String [] args){
     TestStream s=TestStream.getTest();
     s.setName(" Zhang Xiaoxiang ");
    System.out.println(s.getName());
     TestStream s1=TestStream.getTest();
     s1.setName(" Zhang Xiaoxiang ");
     System.out.println(s1.getName());
     s.getInfo();
     s1.getInfo();
     if(s==s1){
       System.out.println(" It creates the same 1 An instance ");
    }else if(s!=s1){
       System.out.println(" It's not the same thing 1 An instance ");
     }else{
       System.out.println("application error");
     }
   }
 }

Operation results:

Zhang Xiaoxiang
Zhang Xiaoxiang
Zhang xiaoxiang, output message
Zhang xiaoxiang, output message
The same instance is created

Conclusion: the results show that the singleton pattern provides an object-only access point for an object-oriented application, and the entire application shares one instance object, no matter what function it performs.

1. Hungry Chinese singleton class


// Hungry Chinese singleton class . When the class is initialized, it is instantiated by itself  
 public class Singleton1 {
   // Private default constructor 
   private Singleton1() {}
   // It has been self-instantiated  
   private static final Singleton1 single = new Singleton1();
   // Static factory method  
   public static Singleton1 getInstance() {
     return single;
   }
 }

Lazy singleton class


 // Lazy singleton class . In the first 1 Instantiate on the next call  
 public class Singleton2 {
   // Private default constructor 
   private Singleton2() {}
   // Notice, it's not there final  
   private static Singleton2 single=null;
   // Static factory method  
   public synchronized static Singleton2 getInstance() {
     if (single == null) { 
       single = new Singleton2();
     } 
    return single;
   }
 }

3. Registered singleton class


 import java.util.HashMap;
 import java.util.Map;
 // Register singleton class .
 // similar Spring Inside the method, the class name registration, the next time directly from inside. 
 public class Singleton3 {
   private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
   static{
     Singleton3 single = new Singleton3();
     map.put(single.getClass().getName(), single);
   }
   // The default constructor of the guard 
   protected Singleton3(){}
   // Static factory method , Return of this class only 1 An instance of the 
   public static Singleton3 getInstance(String name) {
     if(name == null) {
       name = Singleton3.class.getName();
       System.out.println("name == null"+"--->name="+name);
     }
     if(map.get(name) == null) {
       try {
         map.put(name, (Singleton3) Class.forName(name).newInstance());
       } catch (InstantiationException e) {
         e.printStackTrace();
       } catch (IllegalAccessException e) {
         e.printStackTrace();
       } catch (ClassNotFoundException e) {
         e.printStackTrace();
       }
     }
     return map.get(name);
   }
   //1 A schematic business approach 
   public String about() {  
     return "Hello, I am RegSingleton.";  
   }  
   public static void main(String[] args) {
     Singleton3 single3 = Singleton3.getInstance(null);
    System.out.println(single3.about());
   }
 }

Related articles: