zoukankan      html  css  js  c++  java
  • 设计模式相关面试问题-单例

    单例的介绍:

    • 单例的概念:
      单例模式是一种对象创建模式,它用于产生一个对象的具体实例,它可以确保系统中一个类只产生一个实例。
    • 好处:
      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这个类就是典型单例的场景,也是在实际中大量使用的,如下:

  • 相关阅读:
    【例题 8-11 UVA-10954】Add All
    【例题 8-10 UVA
    【BZOJ1226】学校食堂Dining(状压DP)
    【Tyvj1601】魔兽争霸(主席树,树套树)
    【BZOJ3504】危桥(最大流)
    【BZOJ1812】riv(多叉树转二叉树,树形DP)
    【Vijos1412】多人背包(背包DP)
    【Codevs1907】方格取数3(最小割)
    【Codevs1227】方格取数2(费用流)
    【Tyvj1982】武器分配(费用流)
  • 原文地址:https://www.cnblogs.com/webor2006/p/8990588.html
Copyright © 2011-2022 走看看