小白谈谈单例模式

概念

通过单例模式创建类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类可以直接访问,不需要实例化对象。


介绍

意图:保证一个类仅有一个实例,并提供一个访问它的全局访问点
主要解决:一个全局使用的类频繁地创建和销毁
何时使用:当你想控制实例数目,节省系统资源的时候
如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建

优点
1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
2、避免对资源的多重占用(比如写文件操作)。

缺点:没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

使用场景:
1、要求生产唯一序列号
2、WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
3、创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。


实现方式

(一)饿汉式(可行的)
使用最广泛
类加载到内存后,就会实例化一个单例,jvm保证线程安全
唯一的缺点:不管是否使用,都会在类加载的时候完成实例化

实现代码:
在这里插入图片描述

(二) 饿汉式(可行的)
与一的原理一样,写法方式不同

实现代码:
在这里插入图片描述

(三)懒汉式(不可行的)
虽然达到了按照需求再进行初始化的目的,但是会造成线程不安全

举例说明:比如第一个实例在调用getInstance()的时候,还没执行到new Mgr03那一步,第二个实例也进入了getInstance()的方法,那么就会创建了两个Mgr03对象,所以会造成线程不安全

实现代码:
在这里插入图片描述
实验的效果:
在这里插入图片描述

(四)懒汉式(不可行的)
在三的基础上,通过使用synchronized解决线程不安全的问题,但是这种方式会带来效率下降

实现代码:
在这里插入图片描述
实验结果:
在这里插入图片描述

(五)懒汉式(不可行的)
第四中方式实现的时候,效率下降,因此试图通过在方法中加锁,通过减少同步代码块的方式提高效率,然而还是不可行的,还是会出现线程不安全的问题。

失败的案例:第一个线程在调用getInstance()方法的时候,判断INSTANCE为空,而还没继续往下执行,第二个线程也调用getInstance()方法,也判断INSTANCE为空,并且继续往下执行,创建了一个实例,然后释放锁,第一个线程获得锁之后,又创建了一个新的实例,这就违背了单例

实现代码:
在这里插入图片描述
实现结果:
在这里插入图片描述

(六)懒汉式(可行的)
在五的基础上,进一步改进,于是有了双重判断方式,这种方式大大提高了效率,而且实现了线程安全,外层的判断不可删除,若是删除了,每一次调用方法的时候都要加锁,防止多余的锁
在这里插入图片描述
实验结果:
在这里插入图片描述
注意:这里解释一下为什么 INSTANCE变量需要加volatile?

解释: 实际上此处的volatile是为了禁止指令重排序的,如今CPU对指令都是并发执行的,所以当代码被编译器编译完之后,会对代码进行重新排序,代码的执行顺序可能不是按照当时的编译顺序执行。引入一个知识点,实例化对象这个操作(INSTANCE = new Mgr06()),假设Mgr06类中有字符串类型的age参数,在编译器中,会有这样的三个步骤,首先给这个对象申请内存,第二步给这个成员变量初始化,第三步把这块内存对象赋值给p,在给这个对象申请内存的时候,会对类中的参数初始化,比如先把age设为0,在极其高并发的情况下,可能出现先申明内存空间,然后执行内存空间指向p,这时候产生的p是age = 0 产生的,如果这个对象p就被调用了,就不是我们预期中的对象了。禁止重排序就不会打乱对象声明的顺序,一定是把age赋值了,才把这个内存空间指向p。


(七)静态内部类的方式(可行的)
通过JVM保证单例,加载外部类的时候不会加载内部类,在加载Mgr07类的时候,内部类Mgr07Holder是不会被加载的,所以当要调用getInstance()方法的时候才会把Mgr07Holder加载,从而实现懒加载,保证线程安全是通过jvm,jvm在加载类的时候只加载一次,所以Mgr07,Mgr07Holder也是只加载一次,因此Mgr07Holder中的INSTANCE永远只有一个对象

实现代码:
在这里插入图片描述
实验结果:
在这里插入图片描述

(八)通过枚举类实现(可行的)
不仅可以解决线程同步,还可以防止反序列化
枚举类没有构造方法,所以就算有Mgr08的class,也无法实例化Mgr08的对象,它的反序列化只是枚举类中INSTANCE中的这个值,所以所有Mgr08类中的INSTANCE都是同一个对象

实现代码:
在这里插入图片描述

实验结果:
在这里插入图片描述


本文参考:https://www.runoob.com/design-pattern/singleton-pattern.html
本文的代码:https://pan.baidu.com/s/1WwPej6zPPiF5co24Enymtw
提取码:2bzu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值