Skip to content
进阶

一句话答案

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 版本 + 加一行配置即可获得性能提升

注意事项:

  1. 仍需要连接池限流:

    • 虚拟线程数量可以很大(上万个),但数据库连接池(如 HikariCP)是有限的
    • 需要合理设置连接池大小,避免耗尽数据库连接
    • 虚拟线程在等待连接时会挂起,不会阻塞 carrier thread
  2. 避免 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();
    }
  3. 不适用 CPU 密集型任务:

    • 虚拟线程的优势在于 IO 等待时释放 carrier thread
    • CPU 密集型任务没有 IO 等待,虚拟线程不会带来并行度提升
    • CPU 密集型仍应使用平台线程 + ForkJoinPool

五、Spring Cloud 与微服务基础

追问与易错

追问方向:

  • 观察者模式怎么用?
  • JdbcTemplate 是什么模式?
  • DispatcherServlet 用了什么模式?

易错点:

  • ❌ 只知道模式名不知道具体在哪用
  • ❌ 混淆代理和装饰器在 Spring 中的应用

💡 记忆锚点

Spring是设计模式教科书:工厂(BeanFactory造Bean)、单例(Bean默认单例)、代理(AOP用动态代理)、模板方法(JdbcTemplate封装样板代码)、观察者(ApplicationEvent事件驱动)、策略(HandlerMapping选处理器)。面试说出5个以上加分。