单例设计模式提供了一种在多线程环境下保证
实例唯一性
的解决方案。从线程安全、高性能、懒加载三个维度进行分析,推荐使用Holder方式
或者枚举方式
实现单例模式
前言
- 单例模式的优缺点对比: | 设计模式 | 线程安全 | 性能 | 懒加载 | | —- | —- | —- | —- | | 饿汉式 | 是 | 较高 | 否 | | 懒汉式 | 否 | 较高 | 是 | | 懒汉式 + 同步方法 | 是 | 低 | 是 | | Double Check | 是,但易出现空指针异常 | 高 | 是 | | Double Check + Volatile | 是 | 高 | 是 | | Holder方式 | 是 | 高 | 是 | | 枚举方式 | 是 | 高 | 是 |
1.Holder方式
public class HolderSingleton {
private HolderSingleton() {
super();
}
/** 静态内部类 */
private static class Holder {
private static HolderSingleton instance = new HolderSingleton();
}
/** 获取 Holder 类的静态变量,主动使用实现初始化 */
public static HolderSingleton getInstance() {
return Holder.instance;
}
}
解释:HolderSingleton 类中没有 instance 的静态成员变量,而是放在了静态内部类 Holder 之中,因此 Singleton 类的初始化过程中并不会创建 Singleton 的实例。当 Holder 被 主动使用
的时候会创建 Singleton 的实例。同时 Singleton 实例的创建过程在 Java 程序编译时期收集到了
2.枚举方式
public class EnumSingletom {
private EnumSingletom() {
super();
}
/** 使用枚举类代替 holder,增加懒加载特性 */
private enum EnumHolder {
INSTANCE;
private EnumSingletom instance;
EnumHolder() {
this.instance = new EnumSingletom();
}
private EnumSingletom getInstance() {
return instance;
}
}
/** 主动使用触发枚举类的实例化(有且仅有一次) */
public static EnumSingletom getInstance() {
return EnumHolder.INSTANCE.getInstance();
}
}
解释:枚举类型本身是 final 类型的,不允许被继承。同时枚举类型是线程安全的并且只能被实例化一次。通过将 枚举类 替代 Holder 的方式,可以实现 instance 实例的懒加载。