单例模式

单件模式

常常用来管理共享的资源,注册表设置对象,数据库连接,线程池

单件模式:确保一个类只有一个实例,并提供一个全局访问点。


public class Singleton{
  private static Singleton uniqueInstance;

  //私有构造函数
  private Singleton(){}

  //静态方法
  public static Singleton getInstance()
  {
    if(uniqueInstance == null)
    {
      uniqueInstance = new Singleton();
    }

    return uniqueInstance;
  }

}

多线程需要获取单例时,可能会存在问题,会产生多个对象。
处理多线程的方法:
只要把getInstance()变成同步方法,多线程灾难几乎就可以轻易解决了。
public class Singleton{
  private static Singleton uniqueInstance;

  //私有构造函数
  private Singleton(){}

  //静态方法
  public static synchronized Singleton getInstance()
  {
    if(uniqueInstance == null)
    {
      uniqueInstance = new Singleton();
    }

    return uniqueInstance;
  }

}

但是 同步getInstance()的做法将会拖垮性能,要知道同步一个方法可能造成程序执行效率下降100倍。
有如下几种方案:
1、如果你的应用程序可以接受同步getInstance()造成的额外负担,就不要做额外的处理了。毕竟同步getInstance()的
方法既简单又有效。

2、使用“急切”创建实例,而不用延迟实例化的做法
如果应用程序总是创建并使用单件实例,或者在创建和运行时方面的负担不太繁重,可以使用此方法。
public class Singleton{
  private static Singleton uniqueInstance = new Singleton();

  //私有构造函数
  private Singleton(){}

  //静态方法
  public static Singleton getInstance()
  {
    return uniqueInstance;
  }

}

利用这个做法,我们依赖JVM在加载这个类时马上创建此唯一的单件实例。
JVM保证在任何线程访问uniqueInstance静态变量之前,一定先创建此实例。

3、
用“双重检查枷锁”,在getInstance()中减少使用同步
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变量被初始化成Singleton实例时,多个线程正确地处理uniqueInstance变量。

如果性能是关心的重点,那么这个做法可以帮助你大大减少getInstance()的时间消耗。

note:
如果使用多个类加载器,可能导致单件类失效而产生多个实例。

原文地址:https://www.cnblogs.com/zhangxuan/p/8398976.html