zoukankan      html  css  js  c++  java
  • 设计模式 单件-Singleton

    单件模式 Singleton

    什么时候使用?当需要独一无二的对象时,请想起他。

    举例:线程池(threadpool),缓存(cache),对话框,处理偏好设置和注册表(registry)的对象,驱动程序对象。

    无需具体例子,先看类图:包含一个private的自己的实例。private的构造函数,确保无法在类以外创建。在getInstance()中检测私有实例是否创建,未则创建,若已存在则直接返回。

    看代码更好理解记忆。

    经典实现方式 Typical Singleton

    public class Singleton {
      private static Singleton uniqueInstance;
      private Singleton() {}
      public static Singleton getInstance {
        if (uniqueInstance == null) {
          uniqueInstance  = new Singleton();
        }        
        return uniqueInstance;
     }            
    }

    经典实现看似完美,但存在问题。它不是线程安全的。当两个线程同时调用的时候,有可能同时进入 uniqueInstance == null 的if块中。这样对象就不是唯一了。后进入的线程会获得一个新的instance。解决方法,马上直观想到,使用synchronized确保线程安全。 

    Singleton Lazy Initialized (延迟加载)

    public class Singleton {
      private static Singleton uniqueInstance;
      private Singleton() {}
      public static synchronized Singleton getInstance {
        if (uniqueInstance == null) {
          uniqueInstance  = new Singleton();
        }        
        return uniqueInstance;
     }            
    }

    如果对性能要求非常高,以上synchronized确实每次都要判断有性能担忧。可以改进如下。

    Singleton Eagerly Initialized (急切创建)

    public class Singleton {
      private static Singleton uniqueInstance = new Singleton();
      private Singleton() {}
      public static synchronized Singleton getInstance {
        return uniqueInstance;
     }            
    }

    很好的解决问题了。以上利用了JVM加载机制。在加载类的时候就吧实例创建好。除此,还有一种方法。

    Singleton Double-checked Locking (双重检查锁)

    public class Singleton {
      private volatile static Singleton uniqueInstance;
      private Singleton() {}
      public static Singleton getInstance {
        if (uniqueInstance == null) {
          synchronized (Singleton.class) {
              if (uniqueInstance == null) {  
                 uniqueInstance  = new Singleton();
              }
          }
        }        
        return uniqueInstance;
     }            
    }

    以上使用了volatile关键字,使uniqueInstance是线程同步读的。即线程总能读到最新的值。uniqueInstance为null时才进行创建。使用synchrinized确保线程安全。同时在块内再次检测是否需要创建。

  • 相关阅读:
    A+B
    Java(2)数据类型转换、变量和常量
    1002. 写出这个数 (20)
    1001.害死人不偿命的(3n+1)
    ACM算法目录
    《mysql必知必会》学习_第19章
    Redhat 6.1安装ArcGIS Server10.1
    ArcGIS 10.1 for Server安装教程系列—— Linux下的单机安装
    ArcGIS 10.1 for Server安装教程系列—— Linux下的单机安装
    Linux ANSI 乱码问题
  • 原文地址:https://www.cnblogs.com/JackMa/p/5339394.html
Copyright © 2011-2022 走看看