本文基于近期大厂面经及 JDK 21/22/23 新特性趋势整理,涵盖基础、并发、集合、JVM、框架等高频考点。内容侧重技术原理与生产实践结合,适合中高级开发面试准备。
一、Java 基础 & JDK 新特性
当前面试对虚拟线程(Virtual Threads)的关注度极高。Tomcat 或 Spring WebFlux 场景下,建议直接使用虚拟线程池替代传统平台线程池。对于 JDBC、Redis 或 MQ 客户端,配合虚拟线程使用可大幅提升吞吐能力。但需注意,不要在虚拟线程内执行长时间 CPU 密集型计算,这会导致 carrier thread 饿死。
虚拟线程与平台线程对比
| 维度 | 平台线程(传统 Thread) | 虚拟线程(JDK 21+) | 备注 |
|---|---|---|---|
| 内存开销 | 1–2 MB / 线程 | ~几百字节 ~ 几 KB | 百万级无压力 |
| 上下文切换 | 操作系统内核态切换 | 用户态调度(轻量) | 快 10–100 倍 |
| 创建/销毁成本 | 高 | 极低 | 阻塞不贵 |
| 适合场景 | CPU 密集、少量长任务 | IO 密集、高并发短任务 | — |
| 线程池是否还需要 | 需要(控制并发数) | 一般不需要,可直接 new Thread() | 推荐 Thread.ofVirtual().start() |
生产建议:面试中常被追问实际落地场景。JDK 21/22/23 最值得关注的特性优先级如下:
| 优先级 | JEP / 特性 | 稳定状态 | 生产使用场景举例 | 面试加分点回答 |
|---|---|---|---|---|
| ★★★★★ | 虚拟线程(Virtual Threads) | JDK 21 正式 | 高并发 HTTP、消息消费、爬虫、数据库连接池 | '替换 tomcat 线程池,QPS 提升 5–20 倍' |
| ★★★★☆ | 结构化并发(Structured Concurrency) | JDK 23 预览 | 批量任务编排、超时控制、资源自动关闭 | '替代 CompletableFuture 的混乱回调地狱' |
| ★★★★☆ | Scoped Values(范围值) | JDK 21 预览→22 正式 | 线程局部变量的现代化替代(轻量、无继承) | '比 ThreadLocal 更安全、更高效' |
| ★★★★ | String Templates(字符串模板) | 多次预览中 | 日志、SQL、JSON 构建(防注入) | '替代 String.format + 占位符混乱' |
| ★★★☆ | Sequenced Collections | JDK 21 正式 | List / Deque / SortedSet 统一首尾操作 | 'first() / last() / getFirst() 等方法' |
| ★★★ | Record Patterns + switch 模式匹配增强 | JDK 21–23 逐步正式 | 简化 instanceof + 强制转换 + 解构 | '替代繁琐的类型判断 + 强制转换' |
| ★★☆ | 分代 ZGC(Generational ZGC) | JDK 21 正式 | 大堆低延迟 GC(<1ms STW) | '生产环境开启 -XX:+UseZGC -XX:+ZGenerational' |
| ★★ | Foreign Function & Memory API | JDK 22–23 | JNI 现代化替代、直接操作 off-heap 内存 | '调用 C++ 库、Zero-Copy 网络' |
一句话总结:2026 年最值得上生产的是虚拟线程 + 结构化并发 + Scoped Values 这套组合,基本可以取代传统的线程池 + ThreadLocal 模式,极大简化高并发代码。
二、并发 & 多线程
1. JDK 21+ 虚拟线程下,synchronized 还有性能问题吗? 几乎没有。虚拟线程的阻塞不再占用 carrier thread(平台线程),所以 synchronized 导致的阻塞成本大幅降低。但仍建议在高竞争场景优先用 ReentrantLock + Condition,因为 synchronized 在虚拟线程时代优化了很多,但锁升级(偏向 → 轻量 → 重量)过程仍然存在。
2. ThreadLocal 在虚拟线程下还有必要吗? 基本没必要了,推荐用 Scoped Value(JDK 21+)。ThreadLocal 在虚拟线程中会导致内存泄漏风险(因为虚拟线程数量巨大且频繁创建销毁),而 Scoped Value 是结构化的、不可变的值传递,生命周期自动跟随作用域,天然避免泄漏。
3. 说说 AQS 的核心思想?ReentrantLock / CountDownLatch / Semaphore 的实现都依赖它吗? 核心:一个 volatile int state + 一个 CLH 变种的双向链表队列。大部分 JUC 工具类都基于 AQS:ReentrantLock、ReentrantReadWriteLock、CountDownLatch、Semaphore、CyclicBarrier、FutureTask 等。
- state:表示锁状态 / 剩余资源数 / 计数等
- 队列:存放等待线程(Node 节点)
- CAS 修改 state + park/unpark 阻塞唤醒
三、集合 & 容器
1. ConcurrentHashMap 1.8 相对于 1.7 做了哪些优化?为什么放弃分段锁? 核心变化:放弃分段锁原因:1.7 最大并发 = segment 数量(默认 16),1.8 理论并发更高 + 内存利用率更好。
- 放弃分段锁 → 用 CAS + synchronized(只锁链表头 / 红黑树根)
- size() / isEmpty() 等操作不再加锁,而是用 baseCount + CounterCells 累加(类似 LongAdder)
- 扩容时多线程协助(transfer 方法)
- 链表转红黑树阈值 8 + 数组长度 ≥64
2. HashMap 在 JDK 17/21 有哪些新变化? 几乎没有大的 API 变化,但内部有微优化:更好的树化 / 退化逻辑(JDK 16+),配合虚拟线程使用时,迭代器更安全(fail-fast 机制不变)。
四、JVM & GC
Shenandoah GC、ZGC、Epsilon GC、ZGC 分代各自适用场景?
| GC 类型 | 最大暂停时间 | 吞吐量牺牲 | 适用场景 | 是否分代 |
|---|---|---|---|---|
| Shenandoah | <10ms | 中等 | 对延迟敏感、中等堆 | 是 |
| ZGC | <1ms | 中等 | 大堆、低延迟 | 否(21 前) |
| ZGC 分代 | <1ms | 较小 | 大堆 + 高吞吐 | 是 |
| Epsilon | 无 GC | 最高 | 内存充足、短期任务 | — |
分代 ZGC(JDK 21)与普通 ZGC 的区别?生产中怎么开启? 普通 ZGC:非分代,所有对象都用统一处理方式。分代 ZGC:引入年轻代(Eden + Survivor),小对象回收更快。 开启方式(生产推荐):
-XX:+UseZGC -XX:+ZGenerational -Xmx32g -Xms32g
五、Spring / Spring Boot
Spring Boot 3.x(JDK 17+)有哪些重大变化?
- 最低要求 JDK 17
- Jakarta EE 9+(javax.* → jakarta.*)
- AOT 编译支持(GraalVM Native Image 更友好)
- Observability 增强(Micrometer + Tracing)
- 虚拟线程原生支持(Tomcat / WebFlux)
六、场景题 & 设计题
1. 设计一个支持 10w QPS 的秒杀系统,缓存 + 数据库怎么配合? 典型回答框架:前置限流(Sentinel / Nginx)、Redis + Lua 脚本原子扣库存、异步落库(MQ 削峰)、缓存预热 + 热点 key 缓存、虚拟线程处理请求(JDK 21+)、幂等 + 防超卖(唯一订单号 + 去重)。
2. 如何设计一个分布式 Session 方案? 主流三种:Spring Session + Redis(最常用)、JWT(无状态,前后端分离首选)、粘性 Session(Nginx ip_hash)。
七、其他高频补充
- GraalVM Native Image 优缺点?(启动快、内存低,但反射/动态代理受限)
- Project Loom 生态现状?(很多框架 2025–2026 年已适配虚拟线程)
- Java 23 / 24 预览特性了解多少?(关注 Class-File API、Vector API 等)
