Design Patterns (Java language) - Singleton

  Singleton, in short the entire application which is the one and only one instance of the program at any time, any place to which the objects are acquired the same object. Singleton pattern to solve a global classes are frequently created and destroyed, or every time you create or destroy the object in question needs to consume a large amount of cpu resources. The total Singleton pattern can be divided into lazy mode and starving mode, as the name suggests, lazy mode is a very lazy man, as long as you do not have to use it, it will never be instantiated. Starving mode, which means that, man is very hungry, give you allocate memory as long as the compilation phase of the program, created objects.

  The lazy mode and starving mode segments, can be divided into:

  1, lazy mode

  2, starving mode

  3, double-check mode

  4, the internal static class pattern

  5, the enumeration mode

  Whether singleton pattern implemented by which way, which basically has been the creation process: First, the constructor declared as private, thus preventing direct new a new object. Second, we declare a private member variable, namely singleton object. The third step is to declare a public static method for acquiring or creating a singleton object, the object must want to get outside obtained through this method.

  First, the lazy thread-safe mode 1--

/**
 * 饿汉模式1
 */
public class HungrySingleton1 {

    private static HungrySingleton1 singleton = new HungrySingleton1();

    private HungrySingleton1(){}

    public static HungrySingleton1 getInstance() {
        return singleton;
    }


}

  The advantage of this model is lazy implementation is very simple. The disadvantage is lazy and play the effect of loading, if the project is not used to this object will be a waste of resources.

 

  Second, starving thread safe mode 1--

/**
 * 懒汉模式1
 */
public class LazySingleton1 {

    private static LazySingleton1 singleton;

    private LazySingleton1(){}

    public static LazySingleton1 getInstance() {
        if (singleton == null) {
            singleton = new LazySingleton1();
        }
        return singleton;
    }


}

  Although such an approach to achieve the effect of lazy loading, but in the strict sense is not a singleton, because there may be in a multithreaded environment will create a number of different objects, as to why, I do not understand can look at the between writing articles about Java memory model. Such an approach can only be applied to single-threaded environment, significant limitations. Practice is strongly not recommended to use this method.

 

  Third, lazy thread-safe mode 2--

  

/**
 * 懒汉模式2
 */
public class LazySingleton2 {

    private static LazySingleton2 singleton;

    private LazySingleton2(){}

    public static synchronized LazySingleton2 getInstance() {
        if (singleton == null) {
            singleton = new LazySingleton2();
        }
        return singleton;
    }


}

  The wording glance, like the above method, such an approach on the way to add the synchronized keyword, thus ensuring you can only have one thread into the body of a method to solve the problem in a lazy mode. The advantage of this wording is to achieve the effect of lazy loading, the disadvantage is very low efficiency, when multiple threads at the same time obtain an instance, it may cause the situation threads blocked. Not recommended.

 

  Lazy mode 3-- thread safe

/**
 * 懒汉模式3
 */
public class LazySingleton3 {

    private static LazySingleton3 singleton;

    private LazySingleton3(){}

    public static LazySingleton3 getInstance() {
        if (singleton == null) {
            synchronized (LazySingleton3.class) {
                if (singleton == null) {
                    singleton = new LazySingleton3();
                }
            }
        }
        return singleton;
    }
}

  The wording has been judged twice singleton == null in actual applications when we call this method, in fact, 99% chance of an instance has been created, so the first singleton == null filter out 99% of calls, do not lock up the method, thus increasing efficiency. The advantage of this method is to achieve the effect of lazy loading, and high efficiency. Code design is still the disadvantage defects, jvm memory allocated for the object and the assignment is not an atomic operation, i.e. singleton = new LazySingleton3 () code in the jvm is achieved by three steps, first to stack will jvm object allocate some memory space, and then complete the initialization of the object, and then point to a memory address to the object. However, we know, jvm at compile time is not always in the order we write the code to execute, but rather based on the optimal order of execution jvm think (this process is called instruction reordering), it is possible in the implementation of step 1 after step 3 is performed, this time the second thread coming singleton found not empty, so the object is returned directly, thus resulting in a null pointer exception.

 

  Fourth, double-check the thread-safe lock mode ---

/**
 * 懒汉模式4
 */
public class LazySingleton4 {

    private volatile static LazySingleton4 singleton;

    private LazySingleton4(){}

    public static LazySingleton4 getInstance() {
        if (singleton == null) {
            synchronized (LazySingleton4.class) {
                if (singleton == null) {
                    singleton = new LazySingleton4();
                }
            }
        }
        return singleton;
    }
}

  Compared to the above approach, which only added to the member variables in the volatile keyword, solve the problem of instruction reordering, while ensuring that the current thread change this variable, other threads can timely read the latest value. Disadvantage of this method is to write more complicated, requiring the programmer to jvm better understanding. The advantage is not only to ensure the thread safety, but also to ensure a relatively high efficiency.

 

  Fifth, static inner classes mode - thread-safe

/**
 * 懒汉模式5
 */
public class LazySingleton5 {

    private LazySingleton5(){}

    private static class Holder {
        private static final LazySingleton5 INSTANCE = new LazySingleton5();
    }

    public static LazySingleton5 getInstance() {
        return Holder.INSTANCE;
    }

}

  The wording achieve thread-safety problem is relatively simple, namely to achieve the effect of lazy loading, but also to ensure that multi-threaded environment. This is recommended.

 

  Sixth, the enumeration mode - thread-safe

  

/ ** 
 * Lazy mode. 6 
 * / 
public enum {LazySingleton6 

   INSTANCE 

} 

// Use
public class Test {

public static void main(String[] args) {
LazySingleton6 instance = LazySingleton6.INSTANCE;
LazySingleton6 instance1 = LazySingleton6.INSTANCE;
System.out.println(instance == instance1);

}

}

  The recommended wording, simple and efficient. Full use of the characteristics of the enumeration class defines only one example, and enumerated classes is a natural support for multithreading.

Guess you like

Origin www.cnblogs.com/rainple/p/11886524.html