Java单例模式是一种常用的设计模式,用于确保一个类只有一个实例,并提供一个全局访问点。单例模式广泛应用于需要控制实例数量、节省资源或者需要在全局范围内访问特定实例的场景。以下是五种经典的Java单例类创建方式及其解析与实例代码。
1. 懒汉式(懒加载)
懒汉式单例在第一次使用时创建实例,避免了在类加载时就创建实例带来的资源浪费。
解析:
- 使用
private static关键字声明实例变量。 - 使用
private构造方法防止外部直接实例化。 - 提供一个公共的静态方法获取实例,该方法中判断实例是否存在,不存在则创建。
实例代码:
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
2. 饿汉式
饿汉式单例在类加载时就创建实例,保证了线程安全。
解析:
- 使用
private static final关键字声明实例变量。 - 提供一个公共的静态方法直接返回实例。
实例代码:
public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton() {}
public static EagerSingleton getInstance() {
return instance;
}
}
3. 静态内部类
静态内部类单例利用类加载机制实现延迟加载,同时保证了线程安全。
解析:
- 创建一个内部类
SingletonHolder,其中包含单例实例。 SingletonHolder仅在第一次使用时才会被加载,保证了延迟加载。- 由于外部类
Singleton在加载时不会创建SingletonHolder,所以实例也不会被创建。
实例代码:
public class StaticInnerClassSingleton {
private static class SingletonHolder {
private static final StaticInnerClassSingleton instance = new StaticInnerClassSingleton();
}
private StaticInnerClassSingleton() {}
public static final StaticInnerClassSingleton getInstance() {
return SingletonHolder.instance;
}
}
4. 枚举
枚举是实现单例的简洁方式,也是防止多次实例化的最佳方式。
解析:
- 使用
enum关键字定义枚举类。 - 枚举实例默认是单例的,每个枚举常量都隐式实现了
Singleton接口。
实例代码:
public enum EnumSingleton {
INSTANCE;
public void someMethod() {
// 业务逻辑
}
}
5. 双重校验锁(DCL)
双重校验锁是一种在多线程环境下提高性能的单例创建方式。
解析:
- 使用
volatile关键字防止指令重排序。 - 使用
synchronized关键字加锁,仅在实例未创建时进行加锁。
实例代码:
public class DoubleCheckedLockingSingleton {
private volatile static DoubleCheckedLockingSingleton instance;
private DoubleCheckedLockingSingleton() {}
public static DoubleCheckedLockingSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedLockingSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedLockingSingleton();
}
}
}
return instance;
}
}
以上就是五种经典的Java单例类创建方式的解析与实例代码。在实际应用中,应根据具体需求选择合适的方式,以确保单例的线程安全、性能和易用性。
