19、设计模式之单例模式-懒汉式

/**
 * 懒汉式-单例模式
 * 多线程模式慎用,单例模式会失效,为解决这一问题,可以在静态方法上加“synchronized”表明锁住该类本身,同一时间点只有一个线程可以访问该方法
 * 该方法虽然可以解决单例失效的问题,但却非常的消耗资源
 */
public class LazySingleton {
    private static LazySingleton instance = null;

    private LazySingleton(){

    }

    private synchronized static LazySingleton getInstance(){
        if(instance==null){
            instance = new LazySingleton();
        }
        return instance;
    }

    /**
     * 与上述方法等效
     * @return
     */
    private static LazySingleton getNewInstance(){
        synchronized(LazySingleton.class) {
            if (instance == null) {
                instance = new LazySingleton();
            }
        }
        return instance;
    }
}

进一步完善,解决资源占用过多的问题

/**
 * 引入双重锁概念,完善懒汉式-单例模式
 */
public class LazyDoubleCheckSingleton {

    private volatile static LazyDoubleCheckSingleton instance = null;

    private LazyDoubleCheckSingleton(){

    }

    public static LazyDoubleCheckSingleton getInstance(){
        if(instance==null){
            synchronized (LazyDoubleCheckSingleton.class) {
                if(instance==null) {
                    instance = new LazyDoubleCheckSingleton();
                    // 这种方式虽然极大地解决了资源占用多过的问题,但也是存在线程安全性问题
                    // new 一个对象实际执行了三步操作,如下
                    // 1、为对象分配内存地址
                    // 2、初始化对象
                    // 3、将instance指向 新分配的内存地址
                    // 正常情况下,执行顺序1->2->3 如此执行,但多线程会造成重排序现象1->3->2,如要禁止该现象发生,
                    // 只需要在instance变量声明上加入一个关键字“volatile”,
                    // 多线程下 系统会有共享内存,volatile会使所有线程都能看见该变量的最新状态,
                    // 在赋值的时候,会将当前行缓存数据写回到共享内存,这样其他线程缓存的数据就会失效,从而再次向共享内存获取该变量的最新数据
                }
            }
        }
        return instance;
    }
}

第二种完善方式,静态内部类

/**
 * 完善懒汉式-单例模式 第二种方式:静态内部类
 * 由于静态内部类被调用时,系统会先获取类对象锁,这样一来,多线程之间就屏蔽了StaticInnerClassSingleton 类实例化的全过程,
 * 重排序现象仅对当前线程可见且有效
 */
public class StaticInnerClassSingleton {

    private StaticInnerClassSingleton(){

    }
    private static class InnerClass{
        private static StaticInnerClassSingleton instance = new StaticInnerClassSingleton();
    }

    public static StaticInnerClassSingleton getInstance(){
        return InnerClass.instance;
    }
}

【切记】单例模式,一定要记得创建私有构造函数

猜你喜欢

转载自blog.csdn.net/crystalcs2010/article/details/83272095