美文网首页
单例模式的实现方式

单例模式的实现方式

作者: hello_cc | 来源:发表于2016-01-14 17:29 被阅读48次

最近看到组里有人实现单例模式,采用静态内部类的方式,不是很懂这种写法的优点,查了一下各种写法的优缺点,总结一下。
内容多处参考文章:http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern/

懒汉式

public class Single {

      private static Single mInstance;
      private Single(){}

      // 线程不安全
      public static Single getInstance() {
          if (mInstance == null) {
              mInstance = new Single();
          }
          return mInstance;
      }

      // 线程安全,效率低,只有一个线程能调用getInstance()方法。
      public static synchronized Single getInstance() {
          if (mInstance == null) {
              mInstance = new Single();
          }
          return mInstance;
      }

      // 同步代码块加锁,双重检查锁。
      public static Single getInstance() {
          if (mInstance == null) {  //Single Checked 
              synchronized (Single.class) {
                  if (mInstance == null) { //Double Checked 
                      mInstance = new Single(); 
                  } 
              } 
          } 
          return mInstance ;
      }
}

同步代码块加锁,双重检查

  • 这个是平时最常用的方式,看似完美,其实是有问题的。
    因为mInstance = new Single();这句语句的执行,不是一个原子操作,JVM在执行这条语句时,做了3个操作。
  1. 给mInstance分配内存。
  2. 调用Single的构造方法进行初始化。
  3. 将mInstance对象指向分配的内存空间(执行完这步mInstance就非空啦)。

但是在 JVM 的即时编译器中存在指令重排序的优化。也就是说上面的第二步和第三步的顺序是不能保证的,最终的执行顺序可能是 1-2-3 也可能是 1-3-2。如果是后者,则在 3 执行完毕、2 未执行之前,被线程二抢占了,这时 instance 已经是非 null 了(但却没有初始化),所以线程二会直接返回 instance,然后使用,然后顺理成章地报错。

饿汉式

public class Single {
      // 类加载时就被初始化,线程安全
      private static final Single mInstance = new Single();
      private Single(){}

      public static Single getInstance() {
          return mInstance;
      }
}

缺点

  • 不是懒加载模式,类被加载时就被初始化。
  • 如果构造函数需要传递参数时,不能满足。

静态内部类

public class Single {

      private Single(){}

      private static class InnerHolder {
            private static final INSTANCE = new Single();
      }

      public static Single getInstance() {
            return InnerHolder.INSTANCE;
      }
}

这种写法仍然使用JVM本身机制保证了线程安全问题;由于 InnerHolder 是私有的,除了 getInstance() 之外没有办法访问它,因此它是懒汉式的;同时读取实例的时候不会进行同步,没有性能缺陷;也不依赖 JDK 版本。

总结

单例模式最好采用静态内部类实现,但是如果对懒加载参数没有要求,饿汉式也可以。

相关文章

  • 单例模式的常用实现方式

    单例模式属于最常用的设计模式,Java中有很多实现单例模式的方式,各有其优缺点 实现方式对比 单例实现方式线程安全...

  • 设计模式--单例模式

    单例模式概述 单例模式实现方式 为什么要使用单例模式 单例模式实现方式 饿汉式 类加载后就会将对象加载到内存中,保...

  • kotlin实现单例模式

    1.懒汉式实现单例模式 2.线程安全懒汉式实现单例模式 3.双重校验懒汉式实现单例模式 4.静态内部类方式实现单例模式

  • Python经典面试题21道

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • Python最经典面试题21道,必看!

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • Python 经典面试题

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • Python 经典面试题

    1、Python如何实现单例模式? Python有两种方式可以实现单例模式,下面两个例子使用了不同的方式实现单例模...

  • 单例模式(Singleton)- 通俗易懂的设计模式解析

    单例模式的实现方式单例模式的实现方式有多种,根据需求场景,可分为2大类、6种实现方式。具体如下: a. 初始化单例...

  • 2018-06-19 Python中的单例模式的几种实现方式的及

    转载自: Python中的单例模式的几种实现方式的及优化 单例模式 单例模式(Singleton Pattern)...

  • 常见的设计模式

    创建型模式 结构型模式 行为模式 单例模式 单例模式的优点 常见的五种单例模式实现方式 单例带来的问题 如何选择 ...

网友评论

      本文标题:单例模式的实现方式

      本文链接:https://www.haomeiwen.com/subject/ygxhkttx.html