Java 单例模式

java 单例模式指整个程序中只有一个某个类的实例,通常被用来代表那些本质上唯一的系统组件,比如窗口管理器或者文件系统。

《Effective Java》里面的三种方法:

  1. 公有的静态成员:
public class Elvis {
  public static final Elvis INSTANCE = new Elvis();
  private Elvis() {

  }
  public void leaveTheBuilding() {

  }
}
  1. 静态工厂方法
public class Elvis {
  private static final Elvis INSTANCE = new Elvis();
  private Elvis() {

  }
  public static Elvis getInstance() {
    return INSTANCE;
  }
  public void leaveTheBuilding() {

  }
}

工厂方法有两个优势,一是可以改成每个调用该方法的线程都返回一个唯一的实例,二是与泛型有关。

  1. 使用单元素枚举类型
public enum Elvis {
  INSTANCE;

  public void leaveTheBuilding() {

  }
}

这种方法更加简介,而且无偿提供了序列化机制。

其他常用方法

  1. 在工厂方法中初始化单例,按需延迟加载单例
public class Singleton {
  private static Singleton instance = null;
  private Singleton() {

  }
  public static Singleton newInstance() {
    if (instance == null) {
      instance = new Singleton();
    }
    return instance;
  }
}
  1. 第一种方法叫做“懒汉式”加载,多个线程调用newInstance方法会产生多个实例。Effective Java 中的第一、二种方法叫做“饿汉式”加载,在多线程的情况下不会出现问题,因为JVM只会加载一次单例类。可以使用同步锁来解决多线程不安全的问题。
public class Singleton {
  private static Singleton instance = null;
  private Singleton() {

  }
  public static Singleton newInstance() {
    synchronized(Singleton.class) {
      if (instance == null) {
        instance = new Singleton();
      }
      return instance;
    }
  }
}
  1. 双重校验锁方式,可以在上面方法外层加个if语句来提高性能,防止每次通过同步锁来获取单例。
public class Singleton {
  private static volatile Singleton instance = null;
  private Singleton() {

  }
  public static Singleton newInstance() {
    if (instance == null) {
      synchronized(Singleton.class) {
        if (instance == null) {
          instance = new Singleton();
        }
      }
    }
    return instance;
  }
}

注意 instance 是 volatile 变量,保证“对 volatile 变量的写操作,不允许和它之前的读写操作打乱顺序;对 volatile 变量的读操作,不允许和它之后的读写乱序”。

对 volatile 变量的读写操作是一个比较重的操作,上面的方法还可以通过局部变量来优化:

public class Singleton {
  private static volatile Singleton instance = null;
  private Singleton() {

  }
  public static Singleton newInstance() {
    Singleton inst = instance;
    if (inst == null) {
      synchronized(Singleton.class) {
        inst = instance;
        if (inst == null) {
          inst = new Singleton();
          instance = inst;
        }
      }
    }
    return inst;
  }
}
  1. 静态内部类方式
public class Singleton {
  private static class SingletonHolder {
    public static Singleton instance = new Singleton();
  }

  private Singleton() {

  }
  public static Singleton newInstance() {
    return SingletonHolder.instance;
  }
}

JVM进行类加载的时候会保证数据是同步的,内部类只有在使用时才会加载,实现了“懒汉式”的加载和线程安全。

参考文章

  1. 《Effective Java》
  2. Java 单例真的写对了么?
  3. 你真的会用单例模式吗

你可能感兴趣的:(Java 单例模式)