Seven kinds of ways to create a Singleton pattern

  • Singleton ensure only one instance of a class
  • Singleton class must create their own unique instance
  • Singleton class provides a static acquisition mode (usually getInstance () method name)

The first Chinese-style hungry

public class Singleton {

    private static final Singleton instance = new Singleton();

    public Singleton() {
        //Empty
    }

    public static Singleton getInstance() {
        return instance;
    }
}

In the above code you can get to the only instance of a class, but when the process of loading the JVM will initialize this instance, but if not used to this instance, it will cause a waste of memory. This method can be used but is not recommended

The second lazy style

public class LazySingleUnSafe {

    private static LazySingleUnSafe instance;

    private LazySingleUnSafe() {

    }

    public static LazySingleUnSafe getInstance() {
        //一个线程进入了if (null == instance)判断语句块,还未来得及往下执行,
        // 另一个线程也通过了这个判断语句
        if (null == instance) {
            return new LazySingleUnSafe();
        }
        return LazySingleUnSafe.instance;
    }
}

The first method described above solves the problem of starving the formula, but can only be used in a single thread mode, if multiple threads, the first thread when it is determined

if (null == instance)

This sentence is True, a second thread may be judged as Ture, it will create multiple instances, so multiple threads can not be used

The third lazy man locked

public class LazySingleSafe {

    private static LazySingleSafe instance;

    private LazySingleSafe() {

    }

    // 在这里加锁 但是影响性能
    public synchronized static LazySingleSafe getInstance() {
        if (null == instance) {
            return new LazySingleSafe();
        }
        return LazySingleSafe.instance;
    }
}

This way you can solve the problem with the second mode, but each state will determine the lock, so poor performance

The fourth mode DoubleCheck

public class LazySingleDoubleCheck {

    private static LazySingleDoubleCheck instance;

    private LazySingleDoubleCheck() {

    }
    //只有在两个线程同时抢锁的时候
    public static LazySingleDoubleCheck getInstance() {

        if (null == instance) {
            synchronized (LazySingleDoubleCheck.class) {
                if (null == instance) {
                    return new LazySingleDoubleCheck();
                }
            }
        }
        return LazySingleDoubleCheck.instance;
    }
}

This solution to the third lock mode on the method of adding the poor performance issues exist when the instance is determined directly returns the created object instead of the lock status is determined. Even if there are two threads instance is determined null but new instance of the process, locking will be only one thread creates an instance of an object, but if it is in the actual development, if the internal properties of this instance are many examples of the need for a long time, when an object is instantiated still time, if there is a second thread to take this example by getInstance () method, will be taken to a null value.

The fifth DoubleCheck + volatile manner

public class LazySingleDoubleCheckNotNull {

    //在这里加 volatile 保证有序 保证可见性 在读的时候必须保证他已经写完
    private static volatile LazySingleDoubleCheckNotNull instance;

    private LazySingleDoubleCheckNotNull() {
    }

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

This is more than just a way of fourth and added a volatile keyword.
Volatile keyword ensures that a second thread to read when the instance has been completely finished (on this follow-up will focus on keyword description)

The sixth way to create a static inner classes

public class SingleInnerClass {


    private SingleInnerClass() {
    }

    //外部类加载时并不需要立即加载内部类,内部类不被加载则不去初始化INSTANCE 调用的时候只创建一个 所以单例
    private static class InstanceHolder {
        private final static SingleInnerClass instance = new SingleInnerClass();
    }

    public static SingleInnerClass getInstance() {
        return InstanceHolder.instance;
    }
}

JVM when loading external class and inner class does not load immediately, but when called to go to load, so it is similar to the previous mode lazy, and JVM loading mechanism to ensure the security thread, so this approach is recommended.

Seventh enumeration of way

public class SingleEnum {
    private SingleEnum() {
    }
    private enum Singleton {
        INSTANCE;
        private final SingleEnum instance;
        Singleton() {
            instance = new SingleEnum();
        }
        public SingleEnum getInstance() {
            return instance;
        }
    }
    public static SingleEnum getInstance() {
        return Singleton.INSTANCE.getInstance();
    }
}

We define an enumeration, the first time was really used, it will be loaded and initialized virtual machine, and this initialization process is thread safe (on class loader will focus on the follow-up instructions)

Reproduced in: https: //www.jianshu.com/p/9698b0cece09

Guess you like

Origin blog.csdn.net/weixin_33694620/article/details/91245844