外观
一句话答案
Spring 大量使用设计模式:工厂(BeanFactory)、单例(Bean 默认)、代理(AOP)、模板方法(JdbcTemplate)、观察者(事件)。
核心要点
一句话:一行配置开启虚拟线程,同步代码即可处理高并发 IO,不再需要 WebFlux。
开启方式(Spring Boot 3.2+,Java 21+):
yaml
# application.yml
spring:
threads:
virtual:
enabled: true- 加上这行配置后,Tomcat 的请求处理线程自动从平台线程切换为虚拟线程
效果:
- 每个 HTTP 请求分配一个虚拟线程(Virtual Thread)
- 虚拟线程是 JDK 21 引入的轻量级线程,由 JVM 管理调度,创建成本极低(~1KB 栈内存 vs 平台线程 ~1MB)
- 当虚拟线程执行 IO 操作(数据库查询、HTTP 调用、文件读写)时,自动挂起并释放底层 carrier thread
- 一个 carrier thread 可以承载成千上万个虚拟线程
意义:
- 同步代码 + 虚拟线程 = 高并发 IO 处理能力
- 不需要为了高并发而学习响应式编程(WebFlux / Reactor)
- 代码写法和传统 Spring MVC 完全一样,可读性和可调试性更好
- 既有项目只需升级 Java 版本 + 加一行配置即可获得性能提升
注意事项:
仍需要连接池限流:
- 虚拟线程数量可以很大(上万个),但数据库连接池(如 HikariCP)是有限的
- 需要合理设置连接池大小,避免耗尽数据库连接
- 虚拟线程在等待连接时会挂起,不会阻塞 carrier thread
避免 synchronized 导致的 Carrier Thread Pinning:
- 虚拟线程在
synchronized块内执行 IO 操作时,会"钉住"(pin)底层 carrier thread,无法释放 - 解决方案:将
synchronized替换为ReentrantLock
java// ❌ 可能导致 pinning synchronized (lock) { database.query(); // IO 操作 } // ✅ 推荐写法 private final ReentrantLock lock = new ReentrantLock(); lock.lock(); try { database.query(); } finally { lock.unlock(); }- 虚拟线程在
不适用 CPU 密集型任务:
- 虚拟线程的优势在于 IO 等待时释放 carrier thread
- CPU 密集型任务没有 IO 等待,虚拟线程不会带来并行度提升
- CPU 密集型仍应使用平台线程 +
ForkJoinPool
五、Spring Cloud 与微服务基础
追问与易错
追问方向:
- 观察者模式怎么用?
- JdbcTemplate 是什么模式?
- DispatcherServlet 用了什么模式?
易错点:
- ❌ 只知道模式名不知道具体在哪用
- ❌ 混淆代理和装饰器在 Spring 中的应用
💡 记忆锚点
Spring是设计模式教科书:工厂(BeanFactory造Bean)、单例(Bean默认单例)、代理(AOP用动态代理)、模板方法(JdbcTemplate封装样板代码)、观察者(ApplicationEvent事件驱动)、策略(HandlerMapping选处理器)。面试说出5个以上加分。