设计模式:3、单例模式

文章目录

1 、简介

2、单例模式的好处、使用场景 

(1)单例模式的好处

(2)单例模式的使用场景

3、饿汉式

(1)基本步骤

(2)核心代码

4、懒汉式

方式一:懒汉式(线程不安全)

方式二:懒汉式(线程安全)

方式三:懒汉式(DCL双重锁定)

方式四:懒汉式(静态内部类)

5、总结


1 、简介

(1)单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的一个类只有一个实例。即一个类只有一个对象实例。

(2)简而言之使用该模式设计的类,全局应保证只有一个实例。单例模式又称为单实例模式,它的写法很多,如:饿汉式、懒汉式、登记式等。

(3)通常单例模式在java语言中,有两种构建方式:

  • 懒汉方式。指全局的单例实例在第一次被使用时构建。

  • 饿汉方式。指全局的单例实例在类装载时构建。

 

2、单例模式的好处、使用场景 

(1)单例模式的好处

它确保一个类在Java虚拟机里只有一个实例,使一个类只有一个对象,整个系统共享这个对象。也就是阻止new对象,共用一个实例化对象,这样可以有效的节省内存资源,因为它限制了实例的个数,有利于Java垃圾回收(garbage collection)。

(2)单例模式的使用场景

单例模式只允许创建一个对象,它节省内存资源,因此对象需要被公用的场合适合使用,如:

(1)需要频繁实例化然后销毁的对象。 

(2)创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

(3)有状态的工具类对象。 

(4)频繁访问数据库或文件的对象。 

经典使用场景: 

(1)资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如日志文件,应用配置。 

(2)控制资源的情况下,方便资源之间的互相通信。如线程池等。

 

3、饿汉式

在类创建的同时就已经创建好一个静态的对象供系统使用,对象不会再改变。

也就是在类创建的同时,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了。

所以饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题。

(1)基本步骤

单例模式:当前类的实例,全局唯一

1>私有化构造方法( 阻止随便new )

2>定义一个公用的静态的方法,用于获取当前类型的实例

3>定义一个私有的静态的当前类型的实例, 供   步骤2的方法返回

(2)核心代码

这种方式在类加载时就完成了初始化,所以类加载较慢,但获取对象的速度快。 这种方式基于类加载机制避免了多线程的同步问题,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化singletonHungryType显然没有达到懒加载的效果。

4、懒汉式

方式一:懒汉式(线程不安全)

此种方式,没有考虑多线程访问,线程安全问题

方式二:懒汉式(线程安全)

如果是在getInstance2方法上加了一个synchronized,每次调用getInstance2()方法都要对对象上锁

那么我每次去执行getInstace2方法的时候都会受到同步锁的影响,

这样运行的效率会降低,其实只需要在第一次创建SingletonLazy02实例的时候加上同步锁就好了。

方式三:懒汉式(DCL双重锁定

将synchronized关键字加在了内部,也就是说当调用的时候是不需要加锁的,

只有在singletonLazy为null,并创建对象的时候才需要加锁,性能有一定的提升。

也就是如上代码,只有在SingletonLazy03还没被初始化的时候才会进入到第16行,然后加上同步锁。

等SingletonLazy03一但初始化完成了,就再也走不到第16行了,

这样执行getInstance3方法也不会再受到同步锁的影响,效率上会有一定的提升。

这种方法叫做DCL双重锁定(Double-Check Locking)

方式四:懒汉式(静态内部类

还是会有问题,所以有上面的写法。

例如:在Java指令中创建对象和赋值操作是分开进行的,也就是说INSTANCE = new SingletonLazy04();语句是分两步执行的。

但是JVM并不保证这两个操作的先后顺序,也就是说有可能JVM会为新的Singleton实例分配空间,

然后直接赋值给INSTANCE成员,然后再去初始化这个Singleton实例,这样就可能出错了。

 

5、总结

单例模式理解起来简单,但是具体实现起来还是有一定的难度。选择用哪种形式的单例模式,取决于你的项目本身,是否有高并发的环境,还是需要控制单例对象的资源消耗。我们使用的时候,要做到具体情况具体分析,选择适合当前项目开发场景的单例模式。就目前来看,DCL和静态内部类单例模式是高并发场合首选的单例实现方式,在一些对并发要求不高的场合,我们也可以采用其他简单的写法,而不是一味地去追求高并发。

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

被开发耽误的大厨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值