• 单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点
    • 在我们的系统中,有些对象其实只需要一个,比如说,线程池、缓存、对话框、注册表、日志对象、充当打印机、显卡等设备驱动程序的对象。
    • 这类对象只能有一个对象,制造多个可能会导致一些问题的产生:比如程序的行为异常、资源使用过量、或者不一致性的结果
  • 优点:
    • 对于频繁使用的对象,可以省略创建对象所花费的时间
    • 由于 new 操作的次数减少,对系统内存的使用频率也会降低,这将减轻 GC 压力,缩短 GC 停顿时间

 

  • 饿汉方式:全局的单例实例在类加载时构建
  • 懒汉方式:全局的单例模式在第一次被使用时构建

 

  • 饿汉方式
public class Singleton {
       //在静态初始化器中创建单例实例,这段代码保证了线程安全
        private static Singleton uniqueInstance = new Singleton();
        //Singleton类只有一个构造方法并且是被private修饰的,所以用户无法通过new方法创建该对象实例
        private Singleton(){}
        public static Singleton getInstance(){
            return uniqueInstance;
        }
    }
    • JVM 在加载这个类时就创建了此唯一的单例实例,不会存在多个线程创建多个实例的情况,所以线程安全
    • 缺点:这个单例即便没有被使用也会被创建,在类加载之后就被创建,内存就浪费了

 

  • 懒汉方式(添加 synchronized)
public class Singleton {  
      private static Singleton uniqueInstance;  
      private Singleton (){
      }   
      //没有加入synchronized关键字的版本是线程不安全的
      public static synchronized Singleton getInstance() {
          //判断当前单例是否已经存在,若存在则返回,不存在则再建立单例
          if (uniqueInstance == null) {  
              uniqueInstance = new Singleton();  
          }  
          return uniqueInstance;  
      }  
 }
    • 在第一次被使用时创建,如果单例已经被创建了,再次调用接口将不会重新创建新的对象,而是直接返回之前创建的对象
    • 优点:如果某个单例使用的次数很少,并且创建单例消耗的资源较多,那么就需要实现单例的按需创建,使用懒汉模式是个不错的选择
    • 缺点:效率低,第一次加载需要实例化,反应稍慢

 

  • 双重检查单例(DCL实现单例)
public class Singleton {
    //volatile保证,当uniqueInstance变量被初始化成Singleton实例时,多个线程可以正确处理uniqueInstance变量
    private volatile static Singleton uniqueInstance;
    private Singleton() {
    }
    public static Singleton getInstance() {
       //检查实例,如果不存在,就进入同步代码块
        if (uniqueInstance == null) {
            //只有第一次才彻底执行这里的代码
            synchronized(Singleton.class) {
               //进入同步代码块后,再检查一次,如果仍是null,才创建实例
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}
    • 利用双重检查加锁,首先检查实例是否已经创建,如果尚未创建,才进行同步。
    • 优点:资源利用率高,进行了双重的判断,第一层判断主要避免了不必要的同步
    • 缺点:第一次加载时稍慢。

 

  • 静态内部类实现单例
public class Singleton {

    private Singleton() {
    }

    private static class SingletonHolder {
        private static final Singleton INSTANCE = new Singleton();
    }

    public static Singleton getUniqueInstance() {
        return SingletonHolder.INSTANCE;
    }
}
    • 利用了类加载机制来保证只创建一个实例,与饿汉模式一样,也是利用了类加载机制,因此不存在多线程并发的问题
    • 不同的是,是在内部类里面去创建对象实例,这样的话,只要应用中不使用内部类,JVM 就不会去加载这个单例类,从而实现了懒汉方式的延迟加载

 

  • 枚举类实现单例
public enum Singleton {

    INSTANCE;

    private String objName;

    public void doSomething() {}

}
    • 相对于其他单例来说,写法最为简单,并且任何情况下都是单例的。jdk 1.5 之后才有的。
posted on 2019-03-14 18:32  BitingCat  阅读(165)  评论(0编辑  收藏  举报