zoukankan      html  css  js  c++  java
  • 单例模式

    单例模式可以说是最常见而短小的设计模式,这也让它经常在面试中被问到。

    单例模式就是某个类只能生成一个对象。主要应有于某些确实只需要一个对象的情况,比如线程池。

    首先第一步当然是使用private修饰构造方法,这样别人地方就不能用new来新建一个对象。然后在代码中添加一个静态方法,这个方法可以返回一个实例对象。那么怎么控制这个方法只能返回一个对象呢?可以在类里面声明一个以这个类为静态类型的static字段instance。这样每次调用这个方法的时候就检查这个字段是不是null,是的话就new一个并且返回,不是的话就直接返回instance(已经被新建过了)。

    但是如果单纯这样只适用于单线程的情况下,在实际应用中要考虑多线程的情况:A线程判断instance为null就准备新建,可是还没有新建成功返回对象的引用的时候发生了线程调度,B线程也因为这个instance是null而准备开始新建。结果就是产生了两个对象。

    那么在这里需要做的是使这个设计模式线程安全。

    方法有3:

    1,使用synchronized修饰这个方法使其自动加锁实现互斥进入。问题是效率低,如果大量被使用这个方法,会有很大开销,同时只有第一次是真正需要加锁的,但这里以后每一次都有一个没意义的加锁过程。当然这么做也是解决问题的一种方式,如果确实调用很少也不是不可以用。

    2,直接在类的属性声明中新建一个。比如这么写:

    1 private static SingletonClass instance = new SingletonClass();

    这样做的话在JVM加载这个类的时候就会由<clinit>方法自动给他创建一个,以后连对它是否为null的判断都不用了。但是问题也很明显,这样做的话无法在真正需要的时候再新建对象,如果这个对象很大,那么它过长的生命周期会给JVM的堆带来不必要的开销。

    3,双重检查模式

     1 class Singleton {
     2 
     3     private volatile static Singleton instance;
     4 
     5     private Singleton() {
     6 
     7     }
     8 
     9     public static Singleton getInstance() {
    10         if (instance == null) {
    11             synchronized (Singleton.class) {
    12                 if (instance == null) {
    13                     return new Singleton();
    14                 }
    15             }
    16         }
    17         return instance;
    18     }
    19 }

    为什么要两个if判断?第一个if的主要作用是分流,换句话说,在第一次创建之后,很多的调用可以因为这个if直接被pass掉,根本不进入同步代码块,也就减少了不必要的同步的开销。第二个if是保证这个设计模式逻辑成立的关键。如果没有第二个if,可能发生这种情况:线程A因为instance为null进入了代码块,但是发生了线程调度,线程B也随之进入代码块(这个时候instance还是null)。也许有人会问,这个地方不是用synchronized括起来的吗?怎么线程B还能进入?注意synchronized的部分从来不是不准进入而是进入后会阻塞(如果已经有线程进入了的话)。这样接下来线程B阻塞在这里面,等线程A新建了对象之后,如果没有第二个if就会让线程B也新建一个对象。

  • 相关阅读:
    Azure 虚拟机安全加固整理
    AzureARM 使用 powershell 扩容系统磁盘大小
    Azure Linux 云主机使用Root超级用户登录
    Open edX 配置 O365 SMTP
    powershell 根据错误GUID查寻错误详情
    azure 创建redhat镜像帮助
    Azure Powershell blob中指定的vhd创建虚拟机
    Azure Powershell 获取可用镜像 PublisherName,Offer,Skus,Version
    Power BI 连接到 Azure 账单,自动生成报表,可刷新
    Azure powershell 获取 vmSize 可用列表的命令
  • 原文地址:https://www.cnblogs.com/dsj2016/p/5702668.html
Copyright © 2011-2022 走看看