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. 你真的会用单例模式吗
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. 实现单例模式 饿汉模式和懒汉模式单例模式根据实例化时机分为饿汉模式和懒汉模式。饿汉模式,是指不等到单例真正使...
    aaron1993阅读 225评论 0 0
  • 线程安全的单例模式的几种实现方法分享线程安全的单例模式实现有几种思路,个人认为第2种方案最优雅 饿汉式 借助内部类...
    东方灵龙阅读 296评论 0 0
  • 第一种(懒汉式,线程不安全):public class Singleton {private static Sin...
    yljava阅读 4,058评论 0 0
  • 前言 本文主要参考 那些年,我们一起写过的“单例模式”。 何为单例模式? 顾名思义,单例模式就是保证一个类仅有一个...
    tandeneck阅读 2,531评论 1 8
  • 她来自甘肃庆阳,在天津读大学,今年刚满25岁。借着活动,借着自己的一番苦心和一个未完成的愿望,就和诸多有着共同志向...
    生活是很有趣的阅读 241评论 0 0