单例模式是一种创建型设计模式,其核心思想是确保一个类仅有一个实例,并提供一个全局访问点来获取这个实例。在 Java 中实现单例模式主要有以下关键点:
new
关键字创建实例饿汉式是最简单的实现方式,在类加载时就创建实例:
public class EagerSingleton {
// 类加载时就初始化实例
private static final EagerSingleton instance = new EagerSingleton();
// 私有构造函数
private EagerSingleton() {}
// 静态访问方法
public static EagerSingleton getInstance() {
return instance;
}
}
优点:实现简单,线程安全
缺点:类加载时就创建实例,可能造成资源浪费
懒汉式在首次调用时才创建实例,但存在线程安全问题:
public class LazySingleton {
private static LazySingleton instance;
private LazySingleton() {}
// 非线程安全的获取实例方法
public static LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
优点:延迟加载,避免资源浪费
缺点:多线程环境下可能创建多个实例
为了解决线程安全问题,可以对获取实例的方法进行同步:
public class LazySingletonSynchronized {
private static LazySingletonSynchronized instance;
private LazySingletonSynchronized() {}
// 同步方法,保证线程安全
public static synchronized LazySingletonSynchronized getInstance() {
if (instance == null) {
instance = new LazySingletonSynchronized();
}
return instance;
}
}
优点:线程安全,延迟加载
缺点:同步方法开销大,影响性能
结合懒加载和性能优化的双重检查锁定实现:
public class DoubleCheckedLockingSingleton {
// 使用volatile关键字保证可见性和禁止指令重排序
private static volatile DoubleCheckedLockingSingleton instance;
private DoubleCheckedLockingSingleton() {}
public static DoubleCheckedLockingSingleton getInstance() {
// 第一次检查,避免不必要的同步
if (instance == null) {
synchronized (DoubleCheckedLockingSingleton.class) {
// 第二次检查,确保在同步块内没有其他线程创建实例
if (instance == null) {
instance = new DoubleCheckedLockingSingleton();
}
}
}
return instance;
}
}
优点:线程安全,延迟加载,性能优化
缺点:实现复杂,需要理解 volatile 关键字的作用
利用 Java 静态内部类的特性实现高效、线程安全的单例:
public class StaticInnerClassSingleton {
private StaticInnerClassSingleton() {}
// 静态内部类,持有外部类的实例
private static class SingletonHolder {
private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
优点:线程安全,延迟加载,实现简单
缺点:无法传递参数
使用枚举实现单例是最简洁、最安全的方式:
public enum EnumSingleton {
INSTANCE;
// 可以添加实例方法
public void doSomething() {
System.out.println("Singleton method called");
}
}
优点:
缺点:无法实现延迟加载
单例模式在以下场景中经常使用:
单例模式虽然简单,但在实际应用中需要根据具体场景选择合适的实现方式,同时注意处理好各种边界情况,确保单例的唯一性和安全性。