聊透设计模式之单例模式
咱们在面试的时候经常会被问到「能否手写一个单例模式?」,说实话,一般你不开发底层框架,很少用到单例,仅仅从面试的角度,你可以去网上百度,会出来一堆关于单例demo的文章,所以重复造轮子的事情咱们就不做了,我们聊点不一样的。
其实大部分程序员,假如不是开发底层架构,很难自己写单例,单例顾名思义就是
从始至终只new 一个对象,例如我们用到spring框架,存储在SpringContext中的对象默认是单例(@Controller @Service等等)。但是实际生产中
更多的是多实例(比如我们的业务代码,从数据库中读取记录处理)。
其实所谓的「饿汉」和「懒汉」指的是
对象实例化(new)的时机,「饿汉」是啥?就是你上来就让我吃饱,意思是一上来你就给我new这个对象出来。
而「懒汉」恰好相反,因为我懒,所以我先不new,等你真正需要(调用get方法)的时候,我在给你实例化对象。
关于「饿汉」和「懒汉」其实大家知道就ok了,「饿汉」还好,生产中可能会有人用,写起来简单。可能有人会说假如不用这个类,还占用内存,不浪费么。我想说的是,拜托,没用你写它干啥呢?
二、「懒汉」的写法存在线程安全的问题。我想说的是,你真的知道线程安全出现在哪么?
回顾一下线程安全的基础(设计模式的写完,计划写线程安全),多线程环境调用下,为了保证线程安全,java提供了 synchronized关键字通过加锁互斥保证原子性,然后volatile 保证可见和有序性。
因此典型的Double check单例模式诞生了(也叫双重检测)。
Double-Check单例在底层开发中经常会发现它的身影,比如SpringCloud,在Eureka初始化的时候需要读取一些配置(假如有一天你开发底层框架了,也可以这么玩)。
四、其实除了上面这些,还有一个用的相对较多的,通过不加锁类似「懒汉」的单例模式,基于「
静态内部类」来实现。
标签: