1. 饿汉式单例实现
1.1 实现原理
在类加载时就创建唯一实例,不需要额外的同步机制,因此没有运行时的锁开销。实例在类初始化阶段完成,确保全局唯一性,访问通过静态方法返回该实例。
这种方式的核心在于对构造函数进行私有化来防止外部直接创建对象,并通过一个静态、最终的实例引用暴露全局访问点。对于需要确保启动时就具备可用性的场景,这一设计十分直观。
1.2 优点与缺点
优点包括<实现简单、线程安全、无锁开销,没有复杂的初始化时序问题。缺点则在于无条件地在类加载时创建对象,可能造成资源浪费,如果该对象创建成本高或并非所有路径都需要,资源利用率低下。
此外,饿汉式的实例在JVM启动阶段就会存在,即使系统未真正使用它,内存占用是确定性的,这对于资源受限的环境可能带来压力。
public class EagerSingleton {private static final EagerSingleton INSTANCE = new EagerSingleton();private EagerSingleton() {}public static EagerSingleton getInstance() {return INSTANCE;}
}1.3 适用场景
当应用对<启动阶段即可用的单例对象没有额外的延迟需求,且对象创建成本较低时,饿汉式非常合适。对于需要在系统空闲时才完成实例化的场景,应避免使用饿汉式以避免资源浪费。
若系统对内存占用敏感且单例对象的初始化成本较高,考虑使用其他实现方式来实现按需创建和线程安全之间的权衡。

2. 静态内部类(Holder)单例实现
2.1 实现原理
利用私有静态内部类持有外部类的唯一实例,只有在调用getInstance时才完成类的初始化。线程安全由类加载机制保证,不需要显式的同步。
外部类的构造函数仍然为私有,确保外部无法直接构造对象;内部类Holder中引用的实例在第一次使用时初始化,从而实现按需加载。
2.2 优点与缺点
优点包括延迟初始化、实现简单且线程安全,没有同步开销。缺点方面,对复杂的初始化场景不够灵活,需要将实例化逻辑集中在内部类中,若构造流程需要与外部依赖协同,可能略显冗余。
此外,该模式对序列化和反射等场景需额外处理,否则可能会破坏单例性质。 序列化保护和反射防护需额外实现。
public class HolderSingleton {private HolderSingleton() {}private static class Holder {private static final HolderSingleton INSTANCE = new HolderSingleton();}public static HolderSingleton getInstance() {return Holder.INSTANCE;}
}2.3 适用场景
当需要按需创建且线程安全,且对初始化成本比较友好时,Holder模式非常适合。对于高并发、对启动时间要求不极端的应用,Holder模式能在首次访问时完成初始化,同时避免同步开销。
如果后续需要在实例化阶段执行更复杂的前置工作,建议将初始化逻辑与Holder模式结合其他配置或依赖注入框架。
3. 枚举单例实现
3.1 实现原理
通过enum类型来实现单例,Java保证枚举实例的唯一性,并且天然防止了通过反射构造新实例的风险。序列化也自动维护单例性,无需额外处理。
枚举实例本身就是一个常量,通常以INSTANCE作为单例实例名称,后续可以在枚举中定义其他方法来实现功能扩展。
3.2 优点与缺点
优势包括实现极简、天然的线程安全、序列化友好、对反射的防护,几乎没有额外的边界条件需要关注。缺点是仅适用于较简单的单例需求,扩展性和灵活性低,不可随意在实例化时注入依赖。
对于需要大量初始化参数或复杂初始化流程的场景,使用枚举单例可能会显得过于强硬,且不易与现有框架对接。
public enum EnumSingleton {INSTANCE;public void someMethod() {// 单例行为实现}
}4. 双重检查锁定(DCL)单例实现
4.1 实现原理
通过<双重检查锁定结合volatile变量来实现懒加载的单例。外部调用时,首次进入会进行一次低开销的判断,在需要创建实例时才进入同步块,避免在高并发情况下的重复同步。
核心在于确保实例初始化对其他线程可见,并通过synchronized进行保护,避免出现部分构造完成的可见性问题。
4.2 线程安全性与注意事项
该实现能够在高并发场景下保证线程安全,但需要将实例变量声明为volatile,以防止指令重排序导致的可见性问题。正确的实现细节是关键,否则仍可能出现并发缺陷。
在某些JVM版本和编译优化条件下,DCL也需谨慎测试,以避免极端情况下的初始化异常。
public class DCLSingleton {private static volatile DCLSingleton INSTANCE;private DCLSingleton() {}public static DCLSingleton getInstance() {if (INSTANCE == null) {synchronized (DCLSingleton.class) {if (INSTANCE == null) {INSTANCE = new DCLSingleton();}}}return INSTANCE;}
}5. 懒汉式(同步方法)单例实现
5.1 实现思路
通过在getInstance()方法上添加synchronized实现懒加载,只有在首次访问时才进行实例化。简单直观,易于理解,但存在同步带来的开销。
私有构造函数用于防止外部直接创建对象,静态字段用于存储全局唯一实例。对于并发量不高的场景,简单实现通常足够。
5.2 优点与缺点
优点是<实现简单且可读性高,在并发极高的场景下仍能保持正确性。缺点是<每次访问都需要获取锁,可能影响吞吐量,尤其在高并发时更为明显。
如果应用对执行吞吐量要求较高,单纯的同步方法实现可能不是最佳选择,应该考虑其他模式或更细粒度的锁策略。
public class LazySingletonSynchronized {private static LazySingletonSynchronized INSTANCE;private LazySingletonSynchronized() {}public static synchronized LazySingletonSynchronized getInstance() {if (INSTANCE == null) {INSTANCE = new LazySingletonSynchronized();}return INSTANCE;}
} 

