返回
单例模式的非传统实现:绕开 synchronized 和 lock
见解分享
2023-10-19 20:28:56
在并发编程中,单例模式至关重要,它确保了一个类只有一个实例。传统上,我们使用 synchronized 或 lock 来实现线程安全性,但有更优雅的方法可以实现这一点,让我们深入探讨一下。
静态内部类
静态内部类是一种嵌套类,只有在外部类被加载后才会加载。Java 类加载器在加载类时遵循单例模式,因此静态内部类的实例在第一次被引用时才会被初始化。
public class Singleton {
private static class SingletonHelper {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton() {}
public static Singleton getInstance() {
return SingletonHelper.INSTANCE;
}
}
枚举
枚举也是一种特殊类型的类,它本质上是单例的。枚举中的每个实例都是该类的一个单例,并且在类加载时就初始化。
public enum Singleton {
INSTANCE;
public void doSomething() {
// ...
}
}
饿汉式(延迟初始化)
饿汉式单例在类加载时立即创建实例,并使用 volatile 确保线程可见性。
public class Singleton {
private static volatile Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
为什么借助了 ClassLoader?
Java 类加载器在加载类时遵循单例模式。当一个类被加载时,类加载器会检查该类是否已经被加载。如果已经被加载,它将返回已经加载的类实例,否则会创建一个新的实例。
静态内部类、枚举和饿汉式单例都利用了这一特性。静态内部类仅在外部类被加载时加载,枚举在类加载时被初始化,而饿汉式单例在类加载时立即创建实例。
结论
除了传统的 synchronized 和 lock,还有许多其他方法可以实现单例模式。静态内部类、枚举和饿汉式(延迟初始化)都是非传统但有效的替代方案。这些方法利用了 Java 类加载器的单例特性,提供了一种线程安全且优雅的单例实现。