几种线程安全的单例

DCL(双重检查加锁)

public class Singleton
{
    //volatile确保对singleton的读写操作不会同时进行,不会出现读取到错误值的情况
    //如果不用volatile进行修饰,可能会出现在getInstance()时读取到错误值的情况,因为new不是原子操作,包含了好几步操作,这几步操作很可能是这样:使singleton对象与引用相关联发生在初始化singleton之前,这种操作在单线程下看对后面是不会有影响的,但是多线程会造成另一个线程调用getInstance()时发现singleton不是null,但其实还没有初始化完毕导致读到错误的值
    private volatile Singleton singleton = null;
    //建议所有的单例模式构造器都是私有的,防止在类外部建立多个实例
    private Singleton()  {}
    public static Singleton getInstance()   {
        //第一次检查是否已经生成了实例
        if (singleton== null)  {
            synchronized (Singleton.class) {
                //如果有多个线程获得了这个锁,第二次检查确保第二个线程进来不会再次生成新的实例
                if (singleton== null)  {
                    singleton= new Singleton();
                }
            }
        }
        return singleton;
    }
}

提前初始化模式

public class Singleton
{
    //在类被加载的时候就会生成singleton实例,所以不会有线程安全问题
    private static Singleton singleton = new Singleton();
    private Singleton()  {}
    public static Singleton getInstance()   {
        return singleton;
    }
}

延长初始化占位类模式

public class Singleton {
    //加载Singleton类的时候不会加载SingletonHolder类,只有第一次访问SingletonHolder类时才会加载
    private static class SingletonHolder {
        private static Singleton INSTANCE = new Singleton();
    }
    private Singleton (){}
    public static Singleton getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

枚举实现单例模式

public enum Singleton{
    INSTANCE;

    public void test() {
        System.out.println("你调用了test()!");
    }
}

枚举类默认构造方法就是私有的,并且只能是私有的.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章