Core principle: Privatize constructors and get unique instances through a static internal method.

The singleton pattern is defined to ensure that there is only one instance of a class and to avoid producing multiple objects that consume excessive resources. There are several common ways to implement the singleton pattern.

Hunchman mode is when the static class is declared the object already exists and initialized.

public class Singleton{ private static Singleton mInstance = new Singleton(); Public static Singleton public static Singleton public static SingletongetInstance() {static methodreturn mInstance;
  }
  private Singleton() {// Note that the constructor must be private}}Copy the code

Advantages: Easy to write, thread safe. Disadvantages: consumption of resources, because even if you do not use the singleton, space will still be allocated to the instance in static storage.

Lazy mode It is lazy loading mode. Load it when you’re using it, and take up no space when you’re not

public class Singleton{
private static Singleton mInstance;
public static synchronized Singleton getInstance() {// note that synchronized must be added here, otherwise multithreaded calls will have problems obtaining more than a unique instance.if(mInstance == null) {
     mInstance =new Singleton();
  }
  returnmInstance; }}Copy the code

Advantages: Multi-threaded security, better than hungry mode, which instantiates Singleton objects only when needed. Disadvantages: Synchronized locks are added to getInstance, so other threads must wait while calling, resulting in unnecessary resource overhead.

The DCL Double Check Lock mode is initialized and does not require the getInstance method for synchronization

public class Singleton{ private static volatile Singleton mInstance; Public static Singleton (volatile)getInstance() {
       if(mInstance == null) {synchronized(Singleton. Class){// Synchronized (Singleton. Class)if(mInstance == null) {// Check mInstance =new Singleton(); }}}returnmInstance; }}Copy the code

MInstance =new Singleton(); mInstance =new Singleton(); Instead of an atomic operation, the compiler basically does three things: 1) allocates memory to the Singleton; 2) initializes member variables using constructors; and 3) points a mInstance to the storage space allocated by the Singleton

The problem is that the Java compiler allows the processor to execute out of order, so it could be 1->3->2. For example, two threads A and B call getInstance static function, and A executes 1->3->2. When executing 3, Thread B’s call getInstance static function returns a mInstance that is not empty. If the mInstance is not empty, thread B’s call getInstance static function returns a mInstance that is not empty. Thread B’s call getInstance static function returns a mInstance that is not empty. This call will result in an error. For this reason, volatile was introduced in JDK1.5 to make the compiler execute 1->2->3 each time, so that there are no multithreading problems and threads are safe.

Advantages of DCL: The utilization of resources is high, and the corresponding space is initialized only when it is used. And efficient implementation of thread synchronization. Disadvantages of the DCL: The use of the volatile keyword makes it slightly slower to load the first time.

Static internal class it is the use of Java virtual machine load class features to solve the thread safety, resource consumption and other problems.

  public  class Singleton {

       private Singleton() {
        }

        public static Singleton getInstance() {
            return SingletonHolder.mInstance;
        }

        public static class SingletonHolder {
            private static final Singleton mInstance = new Singleton()
        }

 }
Copy the code

This approach ensures concurrent access through the JVM class loading method (the virtual machine ensures that the initialization of a class is properly locked and synchronized in a multithreaded environment), and implements lazy loading due to the loading nature of static internal classes, which are loaded at the time of use.

Advantages: Thread safety and lazy loading disadvantages: Must rely on Java virtual machines

Enumerated the singleton

public enum Singleton{
INSTANCE;
}
Copy the code

Advantages: Single-element enumerations not only avoid multithreaded synchronization problems, but also prevent the creation of new objects during deserialization

Android uses a singleton example

public final class InputMethodManager { static InputMethodManager sInstance; . public static InputMethodManagergetInstance() {
        synchronized (InputMethodManager.class) {
            if (sInstance == null) {
                IBinder b = ServiceManager.getService(Context.INPUT_METHOD_SERVICE);
                IInputMethodManager service = IInputMethodManager.Stub.asInterface(b);
                sInstance = new InputMethodManager(service, Looper.getMainLooper());
            }
            returnsInstance; }}...Copy the code

InputMethodManager, for example, exploits the lazy-loaded pattern, but is not thread-safe. The volatile keyword is not added

public static synchronized CalendarDatabaseHelper getInstance(Contextcontext)  
{  
    if (sSingleton == null)  
    {  
       sSingleton = newCalendarDatabaseHelper(context);  
    }  
        return sSingleton;  
}  
Copy the code

The CalendarDatabaseHelper class in lazy mode operates on the Calendar database

Conclusion: 1) realize the singleton pattern in three steps: the constructor private, private static variable declarations, provide static for instance methods. 2) if it is a single thread to recommend lazy loading mode, if it is multi-threaded recommended way to achieve single static inner class 3) for database operations, access to resources, provide singleton pattern for IO operations such as the best to deal with