设计模式面试之单例模式常问知识点

以下是以Markdown格式整理的单例模式在面试中的常问知识点,包含结构化的分点、代码示例和关键解析:

设计模式面试之单例模式常问知识点


一、单例模式的定义与核心目标

  • 定义:确保一个类在JVM中仅存在一个实例,并提供一个全局访问点。

  • 核心要素:

  1. 私有化构造方法(防止外部直接实例化)。

  2. 持有私有静态实例引用。

  3. 提供静态公有方法获取实例(如 `getInstance()`)。


二、单例模式的常见实现方式与对比

| 类型 | 特点 | 线程安全 | 适用场景 |

|----------------|--------------------------------------------------------------------------|--------------|----------------------------------|

| 饿汉式 | 类加载时立即初始化实例(静态变量)。 | ✅ 天然安全 | 对象小、频繁访问且无需延迟加载。 |

| 懒汉式(基础) | 延迟加载,首次调用时创建实例。 | ❌ 非安全 | 需延迟初始化的场景。 |

| 懒汉式(线程安全) | 加锁(`synchronized` 方法或代码块)解决线程安全问题。 | ✅ 安全 | 但性能较低。 |

| 双重检查锁(DCL) | 懒加载 + 两次判空 + `synchronized` + `volatile` 防止指令重排。 | ✅ 安全高效 | 高并发下的延迟加载。 |

| 静态内部类 | 利用JVM类加载机制保证线程安全,延迟加载。 | ✅ 安全 | 推荐使用,兼顾安全与延迟加载。 |

| 枚举 | 天然线程安全,防反射、序列化攻击,简洁高效。 | ✅ 安全 | 最推荐实现方式。 |

示例代码:

```java

// 饿汉式

public class Singleton {

private static final Singleton INSTANCE = new Singleton();

private Singleton() {}

public static Singleton getInstance() { return INSTANCE; }

}

// 静态内部类

public class Singleton {

private static class Holder {

static final Singleton INSTANCE = new Singleton();

}

private Singleton() {}

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

}

// 枚举(最推荐)

public enum Singleton {

INSTANCE;

public void someMethod() {... }

}

```


三、线程安全与性能优化

  1. 懒汉式的线程问题:
  • 多线程同时进入 `if (instance == null)` 可能创建多个实例。
  1. DCL的实现与 `volatile` 必要性:

```java

public class Singleton {

private volatile static Singleton instance;

private Singleton() {}

public static Singleton getInstance() {

if (instance == null) {

synchronized (Singleton.class) {

if (instance == null) {

instance = new Singleton(); // 可能指令重排:分配内存 → 赋值引用 → 初始化

}

}

}

return instance;

}

}

```

  • `volatile` 作用:禁止指令重排(确保 `new Singleton()` 三步操作顺序正确),保证可见性。
  1. 静态内部类原理:JVM 保证类加载过程线程安全,且只有调用 `getInstance()` 时才会加载内部类并初始化实例。

四、单例模式的破坏与防御

  1. 反射攻击:
  • 通过反射调用私有构造器破坏单例。

  • 防御:在构造器中判断实例是否已存在,若存在则抛出异常。

  1. 序列化破坏:
  • 反序列化会创建新实例。

  • 防御:实现 `readResolve()` 方法返回单例实例。

  1. 克隆破坏:
  • 实现 `Cloneable` 接口可能导致克隆出新对象。

  • 防御:重写 `clone()` 方法返回单例实例或抛出异常。


五、应用场景与注意事项

  1. 适用场景:
  • 资源管理(如线程池、数据库连接池)。

  • 全局配置管理。

  • 日志系统。

  1. 注意事项:
  • 避免滥用单例(增加耦合性,破坏可测试性)。

  • 分布式系统中需使用分布式锁(如Redis)实现集群单例。

  • 有状态对象慎用单例,优先无状态设计。


六、面试加分项:进阶问题与扩展

  1. Spring 单例管理:
  • Spring 默认使用三级缓存 + 双重检查实现单例,类似 DCL 机制。
  1. C++11 中的单例:

```cpp

class Singleton {

public:

static Singleton& getInstance() {

static Singleton instance; // C++11 保证线程安全

return instance;

}

private:

Singleton() {}

};

```

  1. 为什么枚举单例最安全?
  • 枚举本质是单例的语法糖,JVM 保证枚举实例唯一性,天然防反射和序列化。

总结

  • 必掌握:实现方式(尤其 DCL、枚举)、线程安全、防御机制。

  • 推荐实践:优先使用静态内部类或枚举单例,兼顾安全与性能。

  • 面试技巧:结合具体场景(如日志系统、配置管理)说明单例的适用性与设计思路。


希望这份Markdown整理能帮助你系统性掌握单例模式的面试重点!

相关推荐
我命由我1234510 小时前
人脸识别 - 人脸识别选帧
java·人工智能·python·算法·安全·java-ee·人脸识别
宠友信息10 小时前
IM系统开发技术路线分析,即时通讯源码助力快速搭建聊天应用
java·spring boot·redis·websocket·mysql·uni-app·vue
long31610 小时前
封装(Encapsulation)
java·人工智能·ai·ai编程
yaoxin52112310 小时前
502. Java 反射 - 编写 MessageInterceptor 类
java·开发语言
风流 少年10 小时前
Spring AI 2.0:阿里云百炼平台(工作流应用)
java·后端·spring
长谷深风11110 小时前
AI Tool 设计:粒度、参数与错误恢复怎么做
java·大数据·人工智能·ai agent·agent工作流·智能体设计·ai产品设计
QQ_216962909612 小时前
【项目编号:project95315】SpringBoot公共自习室管理系统:座位预约、房间管理、签到核销、公告规则完整实战
java·spring boot·后端
嵌入式阿蔡12 小时前
面试高频考点 01:volatile / 中断 / 堆栈 八股精讲
java·面试·职场和发展·嵌入式实时数据库
秋饼12 小时前
LangChain4j + Java 实现企业级 Text-to-SQL 智能问数系统:从自然语言到安全可控的数据洞察
java·ai·技术分享·后端开发
Escalating_xu12 小时前
【C++ STL简介】从六大组件到容器、迭代器与算法协作
java·c++·算法