设计模式——单例模式

场景

在学习Mybatis或者Hibernate中,有一个SqlSessionFactory对象。此对象属于重量级对象,消耗的资源比较大,也只需要存在一个即可。类似的对象还有,线程池、缓存、日志等。这种情况下,就可以使用单例模式来进行控制对象的创建,确保只存在一个。

饿汉模式

懒汉的的单例模式顾名思义就是,在使用前就已经完成的初始化。
代码:

public class HungrySingleton {

    //类装载时就完成初始化
    private static HungrySingleton hungrySingleton = new HungrySingleton();

    //申明私有的构造方法,无法外部通过new初始化对象
    private HungrySingleton() {

    }

    public static HungrySingleton getSingleton() {
        System.out.println("获取单例对象");
        return HungrySingleton.hungrySingleton;
    }
}

这样的写法很简单,但由于在类装载时就完成了初始化,可能会造成一定的资源浪费,但是不存在多线程的问题,比较常见。

静态内部类

代码:

public class StaticHungrySingleton {

    private StaticHungrySingleton() {

    }

    private static class Singleton{
        private static final StaticHungrySingleton staticHungrySingleton = new StaticHungrySingleton();
    }

    public StaticHungrySingleton getSingleton() {
        return Singleton.staticHungrySingleton;
    }
}

相对于上面的方法,静态内部类实现了延迟加载的效果,当StaticHungrySingleton 调用getSingleton()方法时,才会触发静态内部类的初始化过程。

懒汉模式

饿汉模式是在类装载的时候就完成了初始化,懒汉模式在被调用的时候才进行初始化,不会造成内存的浪费问题。
代码:

public class LazySingleton {

    private static LazySingleton lazySingleton;

    //申明私有的构造方法,无法外部通过new初始化对象
    private LazySingleton() {

    }

    public static LazySingleton getLazySingleton() {
        //多线程中,可能出现问题,导致多次初始化
        if (lazySingleton == null) {
            System.out.println("完成懒汉加载");
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}

在多线程中,一个线程准备创建一个对象,这时另一个线程进入if条件判断中,此时对象还未创建,两个线程都将创建对象。

懒汉—Version2.0

public class LazySingleton {

    private static LazySingleton lazySingleton;

    //申明私有的构造方法,无法外部通过new初始化对象
    private LazySingleton() {

    }

    //同步
    public static synchronized LazySingleton getLazySingleton() {
        if (lazySingleton == null) {
            System.out.println("完成懒汉加载");
            lazySingleton = new LazySingleton();
        }
        return lazySingleton;
    }
}

一整个方法加上synchronized 进行同步,对性能而言会存在很大的问题,再进一步改进。

懒汉—Version3.0

public class LazySingleton {

    /*
     *  使用修饰volatile
     *  1、在内存的语义上,volatile具有内存的可见性,比如一个volatile修改后,将该变量刷回主存中,
     *  能使其他持有该变量的缓存失效,这样就能确保变量是最新的。
     *  2、volatile能防止指令重排序
     */
    private static volatile  LazySingleton lazySingleton;

    //申明私有的构造方法,无法外部通过new初始化对象
    private LazySingleton() {

    }

    //同步
    public static synchronized LazySingleton getLazySingleton() {
        if (lazySingleton == null) {
            synchronized (LazySingleton.class) {
                if (lazySingleton == null) {
                    System.out.println("完成懒汉加载");
                    //不使用volatile修饰,可能会存在lazySingleton指向一个未初始化的对象造成空指针异常
                    lazySingleton = new LazySingleton();
                }
            }
        }
        return lazySingleton;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值