My App

单例模式

Singleton — 确保一个类只有一个实例,并提供全局访问点

一句话理解

全局只允许存在一个该类的实例,对外提供统一的获取入口。

解决什么问题

在很多场景中,一个类的对象只需要也只应该有一份

  • 配置中心(全局配置对象)
  • 日志管理器
  • 线程池、连接池等资源管理类
  • 任务调度器

如果任由外界随意 new 对象:

  • 资源浪费(重复对象)
  • 状态不一致(多份状态难以维护)

怎么写

饿汉式(推荐 —— 简单安全)

类加载时就创建好实例,天然线程安全:

public class Singleton {
    // 类加载时就创建唯一实例
    private static final Singleton INSTANCE = new Singleton();

    // 构造器私有化
    private Singleton() {}

    // 对外提供获取方法
    public static Singleton getInstance() {
        return INSTANCE;
    }
}

三步口诀:构造器私有化 + 静态成员存对象 + 静态方法返回对象

懒汉式(延迟加载)

需要时才创建,但要处理线程安全问题:

public class Singleton {
    private static Singleton instance;

    private Singleton() {}

    // synchronized 保证线程安全,但性能较差
    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

双重检查锁(兼顾性能和安全)

public class Singleton {
    // volatile 防止指令重排序
    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;
    }
}

前端中的单例

在 JavaScript/TypeScript 中,模块本身就是天然的单例:

// config.ts —— 导出的对象就是单例,所有 import 共享同一份
const config = {
  apiUrl: 'https://api.example.com',
  timeout: 5000,
}

export default config

使用场景

  • Spring 中 Bean 的默认作用域就是单例(@Scope("singleton")
  • 数据库连接池(HikariCP)
  • Runtime.getRuntime()
  • 前端的全局状态管理(Zustand store、Redux store)

On this page