美文网首页程序员
小白的设计模式之旅(单例模式)

小白的设计模式之旅(单例模式)

作者: 蓉漂里的小白 | 来源:发表于2018-09-19 17:29 被阅读0次

    单例模式是很常见的一种模式也是很简单的一个设计模式。在我们的项目中用到地方比较多,比如:线程池,缓存,注册表等.。单例的类图也很简单,就只有一个类(只能被实例化一次)。今天就让我们来详细的学习一下单例模式。

    一:什么是单例模式


    定义:确保一个类只能有一个实例,并提供一个全局的访问点

    二:如何实现单例模式


    1:第一版单例模式的诞生

    首先我们需要思考一个问题:如何让一个类只能产生一个实例?

    答案:让外部访问这个类时,在外部不能使用new这个关键字来创建它

    问题又来了:既然不能用new ,我们又该怎样创建对象那!

    答案:让类自己去创建,然后提供一个返回这个实例的static方法!

    这个时候,单例模式的思路就比较清晰了,那接下来就让我们来用code来实现这个模式把!

    Singleton:  利用一个静态变量来保存当前唯一的实例

    SingletonClass: 将构造函数变成private,保证外部无法实例这个类

    getInstance: 提供一个返回唯一实例的接口

    2:第2版单例模式的诞生

    这样的一个单例表面看上去确实挑不出什么问题,如果有一天我们的这个类运行在了

    多线程的环境中?

    好了,让我们来设想一个2个线程的场景:

    线程1运行到第14行的时候,哎悠,时间片到了。

    线程2开始运行了,也要求获取这个单例,并拿到了返回值:singleton,不巧,刚拿到

    返回值,时间片就到了。

    线程1继续开始工作了,他直接运行第15行,又创建了一个实例

    这个时候,在我们的工程中这个单例就出现了2个实例。(哭哭~~~~)

    既然出现问题的地方就是因为在多线程还境我们没有做同步才导致SingletonClass被实例化了多次,那解决方案也很简单啊,直接加个synchronized不就解决了嘛

    好了,见证code的时候就到了

    哈哈,这次加了synchronized关键字后,我门就保证了无论在什么时候都只会有一个线程进去,保证了我们我单例模式的正确性。

    3:第三版单例模式的诞生

    不得不承认,第2版的单例模式确实解决了多线程中第一版的灾难,但第2版真的很完美吗?

    答案当然不是,因为同步加锁,众所周知的缺点那就是浪费性能,因为使用了synchronized后,JVM会先做加锁操作,然后把函数地址,参数压如stack中,等函数执行完成后,再做现场恢复,解锁。这样一来,每次调用这个函数对jvm都是一中累赘啊!

    既然,性能下降是因为synchronized导致的,那么我门是不是可以缩小synchronized的使用范围,尽可能让synchronized只使用在new SingletonClass那一步。

    那来见证我们的Code把!

    :我们使用了一个重要的关键字"volatile"

    volatile: 也是用来做同步的,他和synchronized的不同就是,他不需要加锁,解锁和现场恢复等一些操作,volatile是直接去主存中查询数据。这里为什么需要使用这个关键字,让我们来仔细分析下下面的这种场景:

    线程1:运行到第19行时,jvm 刚刚把内存分配出来而且把引用赋值给singleton。但是还没有执行实例化操作(这种情况是JVM自己调优时有时候会出现的问题)这时候线程1的时间片到了。

    线程2:运行到了13行,发现singleton不为null, 直接那去用了,但是singleton只是一个地址引用,地址里面没有任何的对象。这时候大家都常见的一个异常(object not set an reference )

    4:第四版单例模式的诞生

    虽然我们的第三版已经比较完美了,但是众口难调,还是有人不满意,总是有一些强迫怔就是希望我们完全不使用synchronized。

    既然这么要求,那我们只能创建一个全局的变量了,而且还需要是静态的,这样一来

    就只有在JVM类加载时创建一次,以后就不用再创建,直接使用也不用同步。

    OK了,感觉改起来也很简单,来见证我们的Code吧

    三:单例模式和全局变量


    其实,这个问题我们在面试中会经常遇到,我觉得答案很明显:

    如果使用一个全部变量来替代,就意味这在程序一开始就得把这个类实例化出来不管我们用不用,如果这个类很大,但又从来不用,就很浪费内存。比如我们的第四版单例模式(急加载)

    如果使用的是第三版单例模式(懒加载),优点就是可以什么时候用,什么时候加载,不浪费内存

    相关文章

      网友评论

        本文标题:小白的设计模式之旅(单例模式)

        本文链接:https://www.haomeiwen.com/subject/fmipnftx.html