设计模式相关面试问题-单例

单例的介绍:

  • 单例的概念:
    单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例。
  • 好处:
    1、对于频繁使用的对象,可以省略创建对象所花费的时间,这对于那些重量级对象而言,是非常可观的一笔系统开销。
    2、由于new操作的次数减少,因而对系统内存的使用频率也会降低,这将减轻GC压力,缩短GC停顿时间。

单例的六种写法和各自特点:

  • 饿汉:
    代码:

    缺点:无法对instance实例做延时加载。
    优化:采用懒汉。
  • 懒汉:
    代码:

    但是!!它是线程不安全的,下面做实验:

    缺点:在多线程并发下这样的实现是无法保证实例是唯一的。
    优化:用懒汉线程安全方式。

  • 懒汉线程安全:
    它有两种方式,如下:


    缺点:性能
    优化:DCL

  • DCL(Double-checked Locking双重检查锁):

    但是!!代码还是存在问题,因为这块代码不是原子操作,如下:

    不是原子操作就意味着JVM针对标红的这句话会有如下处理:
    1、给instance分配内存。
    2、调用DCLSingleTon构造方法初始化初始化变量。
    3、将instance这个对象指向JVM分配的内存空间,
    但是!!!JVM有这样一个缺点:在既时编译器中,存在指令重排序的优化,也就是以上说的这三步操作不会按照咱们预期的顺序来执行,有可能第三步在第二步之前,也有可能第二步在第一步之前,这样就会造成线程不安全报错,解决方法如下:

    说到volatile关键字的作用可能都会想到可见性,也就是保证线程在本地不会存有instance的副本,而每次都会到内存中读取,事实上这种说法是不全面的,最主要使用它的原因就是禁止JVM指令的重排序优化。
    缺点:JVM的既时编译器中存在指令重排序的优化。
    优化:静态内部类 / 枚举

  • 静态内部类【推荐】
    为什么会有这种写法,其这是JVM提供的一种同步控制,什么意思?对于static和final关键字都是线程安全的,所以看一下具体写法:

    其中如果getInstance()方法木有调用其类也不会被加载,也就是既可以起到懒汉的效果,又能保证同步安全,而且木有使用synchronized关键字也不会影响性能,另外StaticInnerHolder是私有的也不能被外部所调用,简直完美!
    优点:JVM本身机制保证了线程安全 / 没有性能缺陷。

  • 枚举:
    具体写法如下:

    貌似也太简单了吧,但是!!对于里面的实例方法需要保证线程安全。
    安全:写法简单 / 线程安全【如果自己添加的实例方法和实例变量需要自己控制线程安全】。

总结:

  • 饿汉:无法对instance实例进行延迟加载。
  • 懒汉:多线程并发情况下无法保证实例的唯一性。
  • 懒汉线程安全:使用synchronized导致性能缺陷。
  • DCL:JVM既时编译器的指令重排序。
  • 静态内部类 / 枚举:延迟加载 / 线程安全 / 性能优势。

android中的单例:

Application这个类就是典型单例的场景,也是在实际中大量使用的,如下:

转载于:https://www.cnblogs.com/webor2006/p/8990588.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值