知用网
柔彩主题三 · 更轻盈的阅读体验

单例模式怎么实现 日常维护方法与实用案例

发布时间:2025-12-12 05:52:28 阅读:1 次

单例模式的核心思想

单例模式,说白了就是让一个类在整个程序运行期间,只产生一个实例。就像你们小区的物业办公室,不管有多少住户要报修,最后都是找同一个地方,不会每来一个人就新建一个办公室。在编程里,这种“独一无二”的对象很常见,比如数据库连接池、日志管理器、配置加载器等。

懒汉式:用的时候才创建

这种方式最直白——不到真正需要时,绝不创建实例。适合启动快、使用频率低的场景。

public class LazySingleton {
private static LazySingleton instance;

private LazySingleton() {}

public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}

注意那个 synchronized,它保证了多线程环境下不会出现两个实例。但每次调用 getInstance() 都要加锁,性能有点拖后腿。

双重检查锁定:兼顾效率与安全

为了解决上面的问题,可以改用双重检查。先判断是否为空,再加锁,锁内再判断一次,避免重复创建。

public class DoubleCheckedSingleton {
private static volatile DoubleCheckedSingleton instance;

private DoubleCheckedSingleton() {}

public static DoubleCheckedSingleton getInstance() {
if (instance == null) {
synchronized (DoubleCheckedSingleton.class) {
if (instance == null) {
instance = new DoubleCheckedSingleton();
}
}
}
return instance;
}
}

这里 volatile 很关键,防止 JVM 指令重排导致拿到一个还没初始化完成的对象。

饿汉式:一上来就准备好

和懒汉相反,饿汉式在类加载时就把实例建好,天生线程安全,因为 JVM 会保证类初始化的原子性。

public class EagerSingleton {
private static final EagerSingleton instance = new EagerSingleton();

private EagerSingleton() {}

public static EagerSingleton getInstance() {
return instance;
}
}

缺点是不管用不用,都会占用内存。就像你每天上班前都把伞带上,结果一连晴了半个月。

静态内部类:懒加载 + 线程安全

利用 Java 的类加载机制,既实现了延迟加载,又不用手动加锁。

public class StaticInnerClassSingleton {
private StaticInnerClassSingleton() {}

private static class Holder {
private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
}

public static StaticInnerClassSingleton getInstance() {
return Holder.INSTANCE;
}
}

只有当调用 getInstance() 时,才会触发内部类的加载,从而创建实例。简洁又高效。

枚举方式:防反射攻击的终极方案

前面几种写法都有可能被反射破坏单例(通过暴力调用构造函数)。而枚举天然防止这一点,还能防止序列化破坏。

public enum SingletonEnum {
INSTANCE;

public void doSomething() {
System.out.println("执行任务");
}
}

虽然写法冷门,但在要求绝对安全的场景下,值得推荐。就像保险柜,虽然笨重,但最让人放心。

实际开发中选哪种?如果项目对性能要求不高,直接上静态内部类或枚举;要是想炫技又不怕复杂,双重检查也行。关键是理解背后的原理,而不是死记代码模板。