以下是Java实现单例模式的5种常见写法,添加了便于快速记忆的注释和口诀,并附赠标题:
代码实现(带注释)
// 1. 饿汉式(线程安全)
public class Singleton {
private static final Singleton INSTANCE = new Singleton(); // 类加载时初始化
private Singleton() {} // 私有构造函数
public static Singleton getInstance() {
return INSTANCE;
}
}
// 2. 懒汉式(线程不安全)
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) { // 多线程可能同时进入此分支
INSTANCE = new Singleton(); // 非原子操作,可能创建多个实例
}
return INSTANCE;
}
}
// 3. 懒汉式(线程安全,同步方法)
public class Singleton {
private static Singleton INSTANCE;
private Singleton() {}
public static synchronized Singleton getInstance() { // 同步整个方法,性能差
if (INSTANCE == null) {
INSTANCE = new Singleton();
}
return INSTANCE;
}
}
// 4. 双重检查锁(DCL,线程安全)
public class Singleton {
private static volatile Singleton INSTANCE; // 使用volatile禁止指令重排
private Singleton() {}
public static Singleton getInstance() {
if (INSTANCE == null) { // 第一次检查,不加锁
synchronized (Singleton.class) { // 同步块
if (INSTANCE == null) { // 第二次检查
INSTANCE = new Singleton(); // 避免指令重排导致问题
}
}
}
return INSTANCE;
}
}
// 5. 静态内部类(线程安全)
public class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton(); // 类加载时初始化
}
public static Singleton getInstance() {
return SingletonHolder.INSTANCE; // 调用时触发内部类加载
}
}
// 6. 枚举(最推荐,线程安全,防反序列化)
public enum Singleton {
INSTANCE;
public void doSomething() {
// 方法实现
}
}
记忆口诀
饿汉式
饿汉式最无脑,类加载时就创建
static final来帮忙,线程安全有保障
懒汉式(同步方法)
懒汉式要延迟,synchronized来加持
方法加锁性能差,只适合单线程呀
双重检查锁(DCL)
DCL双重锁,volatile来相助
先检查后加锁,再检查才创建
静态内部类
静态内部类,加载时机妙
调用才加载,线程安全好
枚举
枚举单例最推荐,简洁安全无漏洞
防反射防序列化,一个实例走天下