vlambda博客
学习文章列表

聊透设计模式之单例模式

咱们在面试的时候经常会被问到「能否手写一个单例模式?」,说实话,一般你不开发底层框架,很少用到单例,仅仅从面试的角度,你可以去网上百度,会出来一堆关于单例demo的文章,所以重复造轮子的事情咱们就不做了,我们聊点不一样的。

话说,你真的自己写过单例么?

其实大部分程序员,假如不是开发底层架构,很难自己写单例,单例顾名思义就是 从始至终只new 一个对象,例如我们用到spring框架,存储在SpringContext中的对象默认是单例(@Controller @Service等等)。但是实际生产中 更多的是多实例(比如我们的业务代码,从数据库中读取记录处理)。

下面我们聊聊单例模式中经常提到的几个点。

一、到底什么是「饿汉模式」?什么是「懒汉模式」?

其实所谓的「饿汉」和「懒汉」指的是 对象实例化(new)的时机,「饿汉」是啥?就是你上来就让我吃饱,意思是一上来你就给我new这个对象出来。


而「懒汉」恰好相反,因为我懒,所以我先不new,等你真正需要(调用get方法)的时候,我在给你实例化对象。

聊透设计模式之单例模式


关于「饿汉」和「懒汉」其实大家知道就ok了,「饿汉」还好,生产中可能会有人用,写起来简单。可能有人会说假如不用这个类,还占用内存,不浪费么。我想说的是,拜托,没用你写它干啥呢?

二、「懒汉」的写法存在线程安全的问题。我想说的是,你真的知道线程安全出现在哪么?

聊透设计模式之单例模式


三、Double-Check怎么写?
回顾一下线程安全的基础(设计模式的写完,计划写线程安全),多线程环境调用下,为了保证线程安全,java提供了 synchronized关键字通过加锁互斥保证原子性,然后volatile 保证可见和有序性。 因此典型的Double check单例模式诞生了(也叫双重检测)。

聊透设计模式之单例模式


Double-Check单例在底层开发中经常会发现它的身影,比如SpringCloud,在Eureka初始化的时候需要读取一些配置(假如有一天你开发底层框架了,也可以这么玩)。


四、其实除了上面这些,还有一个用的相对较多的,通过不加锁类似「懒汉」的单例模式,基于「 静态内部类」来实现。