其他分享
首页 > 其他分享> > 设计模式 最基础也最重要的单例模式

设计模式 最基础也最重要的单例模式

作者:互联网

饿汉式单例

顾名思义 很饿很着急 会在程序运行一开始就吧类对象加载出来
所以有着可能浪费资源的缺点
简单例子:

//饿汉式单例
public class Hungry {
    //可能会导致空间的浪费
    private byte[] data=new byte[1024*1024];
    //核心思想 构造器私有化
    private Hungry(){

    }

    private final static Hungry HUNGRY=new Hungry();

    public static Hungry getInstance(){
        return HUNGRY;
    }
}

懒汉式单例

懒汉式单例的思想是 当需要用到我时才创建对象 但是简单的写法会在多线程出现问题

//懒汉式单例
public class LazyMan {
    private LazyMan(){
        System.out.println(Thread.currentThread().getName()+"执行了创建方法");
    }

    private static LazyMan lazyMan;

    public static LazyMan getInstance(){
        if(lazyMan == null) {
            lazyMan = new LazyMan();
        }
        return lazyMan;
    }

    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            new Thread(()->{LazyMan.getInstance();}).start();
        }
    }
}

运行结果可能会随机出现多个线程创建了对象 不符合单例模式的思想

双重锁实现多线程懒汉实现

//懒汉式单例
public class LazyMan {
    private LazyMan(){
        System.out.println(Thread.currentThread().getName()+"执行了创建方法");
    }

    private static LazyMan lazyMan;

    public static LazyMan getInstance(){
        //外层判断主要是优化 使得不是每次都要获取锁
        //双重锁懒汉式 称为DCL懒汉
        if(lazyMan==null){
            synchronized (LazyMan.class){
                if(lazyMan == null) {
                    lazyMan = new LazyMan();
                }
            }
        }
        return lazyMan;
    }

    public static void main(String[] args) {
        for(int i=0;i<10;i++){
            new Thread(()->{LazyMan.getInstance();}).start();
        }
    }
}

通过锁就可以实现只能一个线程获取对象
但是实际上这样在极端情况下也不是安全的 原因在与语句
lazyMan = new LazyMan(); 底层是执行了很多步骤的 同时并不是原子操作
有可能出现第一个线程在创建对象 还没完全创建完毕时 第二个线程判断已经创建完毕 最后返回空对象
解决方法:
添加volatile关键字
private volatile static LazyMan lazyMan;

标签:模式,LazyMan,public,static,private,单例,设计模式,lazyMan
来源: https://www.cnblogs.com/OfflineBoy/p/15244878.html