剑指offer__1__Singleton模式

2019-08-20 15:23:30 浏览数 (1)

题目:设计一个类,我们只能生成该类的一个实例。

要点:既然只生成一个实例,那么必须私有化构造函数

实现的方式有哪些:

  1. 饿汉式(线程安全,无法实现懒加载,浪费资源)
  2. 懒汉式(方法需要加synchronized才能实现线程安全,但这样效率就不如饿汉式了,懒汉式能实现懒加载)
  3. 双重锁判定机制(不建议使用,由于JAVA是实行无序写入的机制,有可能产生错误)
  4. 静态内部类实现(线程安全,可以延时加载)
  5. 枚举类实现(线程安全,不能延时加载)

饿汉模

代码语言:javascript复制
public class Singleton1 {
  private static Singleton1 instance = new Singleton1();
  // 私有化构造函数
  private Singleton1() {}
  public static Singleton1 getInstance() {
      return instance;
  }
}

懒汉式

代码语言:javascript复制
public class Singleton2 {
  // 这里可以延时加载,用的时候再创建对象
  private Singleton2  instance;
  // 私有化构造方法
  private Singleton2() {}
  public static synchronized Singleton2 getInstance() {
      if (instance == null) {
          instance = new Singleton2();
      }
      return instance;
  }
}

双重锁判定机制

代码语言:javascript复制
public class Singleton3 {
  private static Singleton3 instance;
  // 私有化构造方法
  private Singleton3() {}
  public static Singleton3 getInstance() {
      if (instance == null) {// 1
          synchronized (Singleton3.class) {
              if (instance == null) {// 2
                  instance = new Singleton3(); // 3
              }
          }
      }
  return instance;
  }
}
/*1和2俩处进行了判定,也就是进行了俩次判定,文章开头说不推荐使用这
种方式,是因为java实行无序写入的机制,在3处的代码处运行过程中,
 instance对象还没构造完时,这是有现车访问代码1处,且判断instance
不为空,然后返回了3处并没构造好的实例引用,这时就可能产生错误*/

静态内部类

代码语言:javascript复制
public class Singleton4 {
  // 私有化构造函数
  private Singleton4() {}
  // 静态内部类
  private static class SingletonInstance {
    private static final Singleton4 instance = new Singleton4();
  }
  public static Singleton4 getInstance() {
    return SingletonInstance.instance 
  }
}

枚举类

代码语言:javascript复制
public enum Singleton5 {
  // 枚举元素本身就是单例
  INSTANCE;
  // 自己的操作
  public static method() {
    //调用该方法会主动使用Singleton5,INSTANCE将会被实例化
  }
}
// 推荐使用这种方式

小结:不建议使用双重锁判定机制,单例对象、资源占用少,枚举要比饿汉好,目前用的较多的是枚举。

0 人点赞