The singleton pattern

Description:

The singleton pattern, as the name implies, guarantees that there is only one instance object globally and provides access to that object

Features:

  1. Class constructor privatized
  2. Private static variable
  3. Provide common methods to access the instance

Implementation:

Ⅰ LanHanShi

Thread unsafe; Lazy loading

package com.bookmark.designpatterns.singleton;

/ * * *@author: hj
 * @date: 2020-12-19 * to them@description: 1. Lazy, thread unsafe **/
public class SingletonImpl1 {


    // Private variables
    private static SingletonImpl1 singletonImpl1;

    // Privatize the constructor
    private SingletonImpl1(a) {}// Public static methods
     public static SingletonImpl1 getUniqueInstance(a) {
        if (singletonImpl1 == null) { // The thread is not safe. It is possible to create multiple instances
            singletonImpl1 = new  SingletonImpl1();
        }
        returnsingletonImpl1; }}Copy the code

Ⅱ hungry Chinese type

Thread-safe, but resource-consuming, instances are created before they are used

package com.bookmark.designpatterns.singleton;

/ * * *@author: hj
 * @date: the 2020-12-19 bowing *@description: Hunhun-style - thread-safe but resource-intensive, created without using the instance **/
public class SingletonImpl2 {

    private static SingletonImpl2 singletonImpl2 = new SingletonImpl2();

    private SingletonImpl2(a) {}public static SingletonImpl2 getInstance(a){
        returnsingletonImpl2; }}Copy the code

Ⅲ LanHanShi

This is a thread-safe implementation method that adds a synchronization lock to the method of obtaining an instance. This method has poor performance and is not recommended

package com.bookmark.designpatterns.singleton;

/ * * *@author: hj
 * @date: the 2020-12-19 and *@description: lazy - thread-safe, locking methods **/
public class SingletonImpl3 {
    private static SingletonImpl3 singletonImpl3;

    private SingletonImpl3(a) {}public static synchronized SingletonImpl3 getInstance(a) { // Add a lock to the method to ensure thread-safety. However, adding a lock to the method degrades performance and is not recommended
        if (singletonImpl3 == null) {
            singletonImpl3 = new SingletonImpl3();
        }
        returnsingletonImpl3; }}Copy the code

ⅳ Double check lock

Thread safe, using the volatile keyword to prevent JVM instruction reordering

package com.bookmark.designpatterns.singleton;

/ * * *@author: hj
 * @date: the 2020-12-19 double-break *@description: * Double-checked locking - thread-safe * Volatile keyword prevents JVM instruction reordering **/
public class SingletonImpl4 {

    private volatile static SingletonImpl4 singletonImpl4;

    private SingletonImpl4(a) {}public static SingletonImpl4 getInstance(a) {
        if (singletonImpl4 == null) {
            synchronized (SingletonImpl4.class) {// Locking the instantiated part of the code is more efficient than locking the method directly
                if (singletonImpl4 == null) {// This is to prevent multiple threads from entering the first if condition, causing multiple instances to be created
                    singletonImpl4 = newSingletonImpl4(); }}}returnsingletonImpl4; }}Copy the code

V Static inner class implementation

Delayed loading, thread safe

package com.bookmark.designpatterns.singleton;

/ * * *@author: hj
 * @date: the 2020-12-26 who were *@description: Static inner class implementation involves class loading related issues delayed loading, thread safe * * 1. When the parent class is loaded, the SingletonHolder is not loaded, which does not take up memory * 2. INSTANCE is initialized when getInstance is called * 3. This implementation is guaranteed to be thread safe **/ because of the JVM class loading mechanism
public class SingletonImpl5 {

    private SingletonImpl5(a) {}private static class SingletonHolder{
        private static final SingletonImpl5 INSTANCE = new SingletonImpl5();
    }

    public static SingletonImpl5 getInstance(a) {
        returnSingletonHolder.INSTANCE; }}Copy the code

ⅵ Enumeration Implementation

It is thread safe, prevents reflection attacks, and does not create multiple instances after multiple serialization and deserialization

package com.bookmark.designpatterns.singleton;

/ * * *@author: hj
 * @date: the 2020-12-26 16:07 *@description: Enumeration implementation * 1. Thread safety * 2. Can prevent reflection attack, other implementations cannot guarantee, need to add code in the constructor to prevent multiple instantiations - reflection attack: through reflection, using setAccessible() method can set the private constructor orientation level to public * 3. Multiple objects are not created after multiple serialization and deserialization; Other implementations use the transient keyword to modify all variables **/
public enum  SingletonImpl6 {
    /** * Instance */
        INSTANCE;

    private String objName;

    private String getObjName(a) {
        return objName;
    }

    private void setObjName(String objName) {
        this.objName = objName;
    }

    public static void main(String[] args) {
        // Singleton test
        SingletonImpl6 firstSingleton  = SingletonImpl6.INSTANCE;
        firstSingleton.setObjName("first name");
        System.out.println("firstSingleton = " + firstSingleton.getObjName());

        SingletonImpl6 secondSingleton = SingletonImpl6.INSTANCE;
        secondSingleton.setObjName("second name");
        System.out.println("firstSingleton = " + firstSingleton.getObjName());
        System.out.println("secondSingleton = " + secondSingleton.getObjName());

        // Reflect to get the instance test
        SingletonImpl6[] enumConstants = SingletonImpl6.class.getEnumConstants();
        for (SingletonImpl6 enumConstant : enumConstants) {
            System.out.println("objName = "+ enumConstant.getObjName()); }}}Copy the code

conclusion

Thread safety: 2, 3, 4,5,6

To prevent reflection attacks, serialization and unsequence words do not create multiple objects only enumeration implementation