我是摘星,一名全栈开发者,专注 Java后端开发、AI工程化 与 云计算架构 领域,擅长Python技术栈。热衷于探索前沿技术,包括大模型应用、云原生解决方案及自动化工具开发。日常深耕技术实践,乐于分享实战经验与学习心得,希望用通俗易懂的方式帮助开发者快速掌握核心技术。持续输出AI、云计算及开源技术相关内容,欢迎关注交流!
在软件开发中,我们经常遇到需要确保一个类只有一个实例的情况。比如数据库连接池、线程池、配置管理、日志记录器等场景,如果创建多个实例会导致资源浪费或数据不一致的问题。单例模式(Singleton)就是为了解决这类问题而诞生的设计模式。
图1:单例模式应用场景示意图
单例模式属于创建型设计模式,它保证一个类只有一个实例,并提供一个全局访问点。这种模式在Java、C++、Python等多种编程语言中都有广泛应用。
单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通常用于控制资源密集型对象的创建,或者需要严格限制实例数量的场景。
图2:单例模式基本结构
单例模式的核心在于控制实例化过程,确保无论调用多少次创建方法,都返回同一个实例。这主要通过以下机制实现:
图3:单例模式生命周期时序图
/**
* 基础单例实现(非线程安全)
* 适用于单线程环境
*/
public class BasicSingleton {
private static BasicSingleton instance;
// 私有构造函数防止外部实例化
private BasicSingleton() {
System.out.println("BasicSingleton instance created");
}
/**
* 获取单例实例
* @return 单例实例
*/
public static BasicSingleton getInstance() {
if (instance == null) {
instance = new BasicSingleton();
}
return instance;
}
// 示例业务方法
public void showMessage() {
System.out.println("Hello from BasicSingleton!");
}
}
/**
* 线程安全单例实现(同步方法)
* 使用synchronized保证线程安全,但性能较低
*/
public class ThreadSafeSingleton {
private static ThreadSafeSingleton instance;
private ThreadSafeSingleton() {
System.out.println("ThreadSafeSingleton instance created");
}
/**
* 获取单例实例(线程安全)
* @return 单例实例
*/
public static synchronized ThreadSafeSingleton getInstance() {
if (instance == null) {
instance = new ThreadSafeSingleton();
}
return instance;
}
}
/**
* 双重检查锁定单例实现
* 兼顾线程安全和性能
*/
public class DCLSingleton {
// volatile确保多线程环境下可见性
private static volatile DCLSingleton instance;
private DCLSingleton() {
System.out.println("DCLSingleton instance created");
}
/**
* 获取单例实例(双重检查锁定)
* @return 单例实例
*/
public static DCLSingleton getInstance() {
// 第一次检查(无锁)
if (instance == null) {
synchronized (DCLSingleton.class) {
// 第二次检查(有锁)
if (instance == null) {
instance = new DCLSingleton();
}
}
}
return instance;
}
}
/**
* 静态内部类单例实现(推荐)
* 线程安全且实现简单,利用类加载机制保证唯一性
*/
public class InnerClassSingleton {
private InnerClassSingleton() {
System.out.println("InnerClassSingleton instance created");
}
/**
* 静态内部类持有单例实例
*/
private static class SingletonHolder {
private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}
/**
* 获取单例实例
* @return 单例实例
*/
public static InnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
/**
* 枚举单例实现(最佳实践)
* 防止反射攻击和序列化问题
*/
public enum EnumSingleton {
INSTANCE;
// 示例业务方法
public void doSomething() {
System.out.println("EnumSingleton doing something");
}
}
图4:单例模式实现方式选择流程图
Spring框架默认将Bean配置为单例作用域,这是单例模式的典型应用:
// Spring配置示例
@Configuration
public class AppConfig {
@Bean
@Scope("singleton") // 默认就是singleton,可省略
public MyService myService() {
return new MyServiceImpl();
}
}
JDK中的Runtime类就是单例模式的经典实现:
/**
* JDK Runtime类单例实现分析
*/
public class Runtime {
private static Runtime currentRuntime = new Runtime();
public static Runtime getRuntime() {
return currentRuntime;
}
private Runtime() {}
// 其他方法...
}
对比项 | 单例模式 | 静态工具类 |
---|---|---|
实例化 | 可以有实例 | 无实例 |
状态 | 可以维护状态 | 无状态 |
继承 | 可以实现接口,可以继承 | 不能继承 |
多态 | 支持多态 | 不支持 |
内存 | 实例占用内存 | 不占用实例内存 |
实现方式 | 线程安全 | 延迟加载 | 防止反射 | 序列化安全 | 性能 |
---|---|---|---|---|---|
基础实现 | 否 | 是 | 否 | 否 | 高 |
同步方法 | 是 | 是 | 否 | 否 | 低 |
双重检查 | 是 | 是 | 否 | 否 | 中 |
内部类 | 是 | 是 | 否 | 否 | 高 |
枚举 | 是 | 否 | 是 | 是 | 高 |
/**
* 基于Redis的分布式单例实现
*/
public class RedisSingleton {
private static final String REDIS_KEY = "global:singleton:config";
private Jedis jedis;
private RedisSingleton() {
this.jedis = new Jedis("localhost");
}
private static class Holder {
private static final RedisSingleton INSTANCE = new RedisSingleton();
}
public static RedisSingleton getInstance() {
return Holder.INSTANCE;
}
public String getConfig(String key) {
return jedis.hget(REDIS_KEY, key);
}
public void setConfig(String key, String value) {
jedis.hset(REDIS_KEY, key, value);
}
}
/**
* 使用注册表模式管理多个单例
*/
public class SingletonRegistry {
private static Map<String, Object> registry = new ConcurrentHashMap<>();
private SingletonRegistry() {}
public static synchronized Object getInstance(String className) {
Object instance = registry.get(className);
if (instance == null) {
try {
instance = Class.forName(className).newInstance();
registry.put(className, instance);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
return instance;
}
}
在微服务架构中,传统的单例模式需要重新考虑:
单例模式是一种简单但强大的设计模式,正确使用它可以提高系统性能和一致性。通过本文的分析,我们可以得出以下结论:
最佳实践建议:
参考资源: