懒汉式(Lazy Initialization)和饿汉式(Eager Initialization)
说明:
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供全局访问点来访问该实例。在 Java 中,单例模式有两种常见的实现方式:懒汉式和饿汉式。
-
懒汉式(Lazy Initialization):
- 延迟加载实例,即在需要使用实例时才进行实例化。
- 优点是节省了系统资源,在程序启动时不会立即创建实例。
- 缺点是在多线程环境下需要考虑线程安全问题。
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {
// 私有构造方法
}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
饿汉式(Eager Initialization):
- 在类加载时就创建实例,确保在任何时候都能获得该实例。
- 优点是线程安全,无需考虑多线程环境下的同步问题。
- 缺点是在程序启动时就创建实例,可能会造成资源的浪费。
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {
// 私有构造方法
}
public static EagerSingleton getInstance() {
return instance;
}
}
无论是懒汉式还是饿汉式,都可以保证在整个应用程序中只有一个实例存在。选择哪种方式取决于具体的需求和场景。如果需要延迟加载实例并在多线程环境下确保线程安全,可以选择懒汉式。如果希望在任何时候都能获得实例并且不需要考虑线程安全问题,可以选择饿汉式。
需要注意的是,在多线程环境下使用懒汉式时,需要考虑使用双重检查锁定(Double-Checked Locking)或者静态内部类实现等方式来保证线程安全性。此外,还可以考虑使用枚举(Enum)来实现单例模式,因为枚举实例的创建是线程安全的。
双重检查锁定(Double-Checked Locking)实现懒汉式单例模式:
public class LazySingleton {
//防止指令重排
private static volatile LazySingleton instance;
private LazySingleton() {
// 私有构造方法
}
public static LazySingleton getInstance() {
if (instance == null) {
synchronized (LazySingleton.class) {
if (instance == null) {
instance = new LazySingleton();
}
}
}
return instance;
}
}
枚举(Enum)实现单例模式:
public enum EnumSingleton {
INSTANCE;
// 添加其他成员变量和方法
// 构造方法会在实例化时自动调用
public static EnumSingleton getInstance() {
return INSTANCE;
}
}
枚举实现单例模式是最简洁且线程安全的方式。枚举类型的实例是在类加载时被创建,保证了实例的唯一性,并且对多线程是安全的。通过调用EnumSingleton.INSTANCE
可以获取实例。枚举单例模式还可以添加其他成员变量和方法,使其具有更多的功能。
需要注意的是,枚举实现的单例模式是Java中最好的单例模式实现方式之一,可以避免反射、序列化等问题。