1. 先搞清楚现在 Java 面试到底考什么,别盲目背题

如果你最近在准备 Java 面试,可能会发现一个问题:光会背八股文已经不够用了。现在的面试官更看重你能不能把知识点和实际场景结合起来,尤其是当 AI 大模型、高并发、复杂业务这些关键词频繁出现时,单纯记忆答案很容易在场景题里露怯。

我整理过最近半年的真实面经和招聘要求,发现 Java 面试的强度确实上来了。除了传统的 Java 基础、并发编程、JVM、MySQL、Spring,现在普遍会加入三类新内容:

  1. 场景题 :不直接问“HashMap 原理”,而是问“订单超时未支付如何自动关闭,用你的知识设计实现方案”。
  2. AI 大模型结合 :比如“如果让你用 Java 调用大模型接口做智能客服,要注意哪些性能问题?”“如何设计一个支持高并发的 AI 任务调度系统?”
  3. 深度原理+实战排查 :像“线上 CPU 突然飙高,你怎么定位是哪个 Java 线程?”“JVM 老年代满了,但堆内存监控显示正常,可能是什么原因?”

所以,如果你还在按五年前的面试套路准备,大概率会碰壁。下面我会按实际面试中的考察顺序,拆解每个模块需要达到什么程度才能应对当前市场。

2. Java 基础:别以为简单,场景题最爱从这里出题

很多人觉得 Java 基础就是“String、List、Map 怎么用”,但面试官现在更倾向于用实际场景考察你对基础类的理解深度。

2.1 集合类要会解释底层实现和适用场景

比如 HashMap,光知道“数组+链表/红黑树”不够,得能回答这种问题:

场景:我们系统有一个商品缓存,key 是商品 ID(Long 类型),value 是商品信息对象,并发量很高,你会选 HashMap 还是 ConcurrentHashMap?为什么?

合格答案不能只说“ConcurrentHashMap 线程安全”,而要细化到:

  • 如果用 HashMap,即使外部同步,扩容时仍可能卡顿,影响实时接口响应。
  • ConcurrentHashMap 的 segment 设计(JDK8 前)或 CAS+synchronized(JDK8+)如何减少锁竞争。
  • 如果商品 ID 是连续的,是否考虑用 LongAdder 代替 AtomicLong 做计数器。

实际面试中,我遇到过更细的追问:“HashMap 负载因子为什么默认 0.75?如果设为 1 会怎样?”——这需要你理解空间和时间权衡,以及扩容触发条件。

2.2 IO 和 NIO 要能对比出适用场景

很多人在 NIO 上背熟了“非阻塞、多路复用”,但被问到“为什么 Netty 用 NIO 而不是 AIO?”就卡住。你需要知道:

  • Linux 底层 epoll 比 AIO 更成熟,Netty 基于 epoll 封装。
  • AIO 在 Windows 支持较好,但服务器主要是 Linux。
  • NIO 的 ByteBuffer 需要手动 flip,为什么这样设计?(避免二次拷贝)

建议自己写一个简单的 HTTP 服务器,用 BIO、NIO 分别实现,体会线程模型差异。面试时如果能说出“BIO 一个连接一个线程,QPS 上去后线程切换成本高;NIO 用少量线程处理大量连接,但代码复杂度高”,会比纯背概念加分很多。

3. 并发编程:不再只是 JUC 工具类,而是真实问题定位

并发编程是当前面试的重点,尤其是结合线上问题排查。

3.1 线程池参数要会根据场景配置

不要死记“corePoolSize、maxPoolSize、queue”,面试官会给你一个具体场景:

我们有一个订单导出功能,用户点击后后端生成 Excel,高峰期可能同时有几十个导出任务,你怎么设计线程池?

低分回答是“调大 maxPoolSize”。高分回答会包括:

  • 导出任务是 CPU 密集还是 IO 密集?(如果是 CPU 密集,线程数不宜过多)
  • 使用有界队列还是无界队列?(有界避免内存溢出,但需要拒绝策略)
  • 拒绝策略选 CallerRunsPolicy 还是 DiscardPolicy?(CallerRunsPolicy 让提交线程自己运行,能感知到压力)

我建议直接手写一个线程池配置,并解释为什么:

ThreadPoolExecutor executor = new ThreadPoolExecutor(
  4, // corePoolSize:常驻线程,按 CPU 核数设置
  8, // maxPoolSize:突发流量时扩容上限
  30, TimeUnit.SECONDS, // 空闲线程回收时间
  new LinkedBlockingQueue<>(100), // 有界队列,避免 OOM
  new ThreadFactoryBuilder().setNameFormat("export-pool-%d").build(), // 命名线程,方便排查
  new CallerRunsPolicy() // 提交线程自己跑,降级
);

3.2 锁和同步机制要结合 JVM 调优

volatile、synchronized、ReentrantLock 的区别很多人能背,但场景题会这样问:

有一个共享计数器,多线程频繁更新,你用 volatile 还是 AtomicLong?如果竞争激烈呢?

这里要提到 CAS 的 ABA 问题、CPU 空转开销,以及 LongAdder 的分段计数设计。更深入的会问“synchronized 锁升级过程”以及“为什么 JVM 偏向锁被废弃?”(因为维护成本高,在多线程环境下反而性能下降)。

如果你能主动说“可以用 jstack 看锁竞争情况”或“用 arthas 的 monitor 命令统计锁等待时间”,面试官会觉得你有实战经验。

4. JVM:不再是理论,而是线上故障排查能力

JVM 问题在面试中占比越来越高,尤其是内存溢出、CPU 飙高这类线上故障的排查思路。

4.1 内存模型要能画出来并解释

不要只会说“堆、栈、方法区”,要能画出 JVM 内存结构,并标注哪些是线程共享、哪些是线程私有。常见场景题:

线上服务频繁 Full GC,监控显示老年代每次 GC 后剩余空间很小,但堆内存使用率并不高,可能是什么原因?

这可能是因为:

  • 有内存泄漏,对象无法被回收(比如静态 Map 缓存没有淘汰策略)。
  • 大对象直接进入老年代(比如大数组)。
  • 元空间(Metaspace)设置过小,导致频繁 GC。

排查步骤要清晰:

  1. jstat -gc pid 看各区内存变化和 GC 次数。
  2. jmap -histo:live pid 看对象实例数,找可疑类。
  3. 如果怀疑内存泄漏,用 jmap -dump:live,format=b,file=heap.bin pid 导堆转储,用 MAT 分析。

4.2 GC 调优要会说人话

面试官不喜欢听“G1 适合大堆,CMS 已淘汰”,而要你能根据业务特点选 GC。比如:

我们有一个电商应用,要求低延迟,堆内存 8G,你怎么选 GC 算法?

可以这样回答:

  • 如果追求低延迟,优先 G1,设置 -XX:MaxGCPauseMillis=200
  • 如果内存小于 4G,可以用 ParNew+CMS,但注意碎片问题。
  • 如果用 JDK11+,可以尝试 ZGC,但先测试兼容性。

关键是要说明“为什么选”:G1 通过 region 划分和预测模型,尽量控制停顿时间;ZGC 用染色指针实现几乎无停顿,但需要更高版本 JDK。

5. MySQL:重点是索引、事务和优化思路

MySQL 问题几乎必问,但现在已经不止于“索引原理”,而是结合具体业务场景的设计和优化。

5.1 索引设计要考虑实际查询模式

常见场景题:

我们有一个用户表,经常按昵称(varchar)和注册时间(datetime)联合查询,你怎么建索引?

低分回答是“建(昵称, 时间)联合索引”。高分回答会追问:

  • 查询条件是 where 昵称 like '张%' and 时间 between ? and ? 还是 where 昵称=? and 时间>?
  • 如果前缀模糊匹配,联合索引可能失效,需要考虑索引顺序。
  • 如果昵称重复度低,优先把昵称放前面;如果重复度高,时间放前面。

还要提到覆盖索引、索引下推(ICP),以及如何用 explain 看执行计划。

5.2 事务隔离级别要能举例说明

不要只会背“读未提交、读已提交、可重复读、串行化”,要能举例说明:

场景:转账操作,A 给 B 转 100,同时 B 查询余额。如果隔离级别是读已提交,B 可能看到什么?如果是可重复读呢?

这需要你知道:

  • 读已提交:B 可能看到 A 提交后的新余额,但中间状态不可见。
  • 可重复读:B 在事务内多次查询余额一致,但可能遇到幻读(如果同时有新增转账)。
  • 串行化:完全隔离,但性能差。

如果面试官深入,可能会问“MVCC 怎么实现的可重复读?”(通过 undo log 和 read view)。

6. Spring:框架原理要结合设计模式

Spring 问题早已不止于“IoC、AOP”,而是源码级的设计思想。

6.1 Bean 生命周期要能画图并解释扩展点

常见问题:

你在项目中如何自定义 Bean 的初始化逻辑?

合格回答是“用 @PostConstruct 或实现 InitializingBean”。但更好的回答包括:

  • BeanFactoryPostProcessor 和 BeanPostProcessor 的区别(前者处理 bean 定义,后者处理 bean 实例)。
  • 如何用 SmartInitializingSingleton 在所有单例初始化完成后执行逻辑。
  • 面试时如果能画出 Bean 从加载到初始化的完整流程图,并标注每个扩展点,会显得很专业。

6.2 事务传播机制要会结合业务用例

传播机制不是背七种类型,而是理解适用场景:

方法 A 有 @Transactional,调用方法 B(也有 @Transactional),B 异常后 A 是否回滚?

这需要你知道默认的 PROPAGATION_REQUIRED 会在现有事务中运行,B 异常会导致整体回滚。如果 B 是 PROPAGATION_REQUIRES_NEW,则会开启新事务,B 回滚不影响 A。

更实际的场景是“批量处理任务,其中一条失败不影响其他条”,这时可以用 REQUIRES_NEW 或手动管理事务。

7. AI 大模型结合:新趋势,考察技术视野和架构能力

这是最近半年新增的考察点,不一定要求你深入大模型原理,但要知道如何用 Java 技术栈对接 AI 能力。

7.1 高并发下如何调用大模型接口

典型场景题:

公司接入了大模型接口,但 QPS 有限制,如何设计一个系统保证不超限且尽量少让用户等待?

这里考察的是:

  • 用线程池或信号量控制并发请求数。
  • 设置超时和重试机制(但注意大模型接口可能不允许频繁重试)。
  • 如果结果允许延迟,可以用队列异步处理,先返回任务 ID,后续轮询或回调。
  • 如果数据可缓存,对相同问题缓存结果(但要注意用户上下文可能不同)。

7.2 大模型输出结果的后处理

比如:

  • 大模型返回的 JSON 可能格式不规范,如何容错解析?
  • 如果返回内容很大,如何分块传输给前端?
  • 如何监控调用耗时和成功率,并做熔降级?

即使你没有实际项目经验,也要表现出思考过程:“我会用 HttpClient 连接池管理请求,用 Jackson 容错解析,用 Hystrix 或 Resilience4j 做熔断。”

8. 面试准备建议:别盲目刷题,按模块逐个击破

最后给一个可执行的准备计划,按 4 周时间规划:

8.1 第一周:Java 基础+并发编程

  • 每天 2 小时,重点看集合源码(HashMap、ConcurrentHashMap)、线程池参数和锁机制。
  • 练习场景题:自己设计一个缓存系统,考虑并发安全和性能。
  • 工具:用 jstack、arthas 实战分析线程状态。

8.2 第二周:JVM+MySQL

  • JVM:练熟 jstat、jmap、MAT 使用,能分析 GC 日志。
  • MySQL:用 explain 分析慢查询,设计索引。
  • 场景:模拟 CPU 飙高,用 top + jstack 定位;模拟死锁,用 show engine innodb status 查看。

8.3 第三周:Spring+框架整合

  • 读 Spring 源码片段,理解 Bean 生命周期、事务管理。
  • 整合 MyBatis、Redis,知道常见坑点(比如缓存穿透、雪崩)。
  • 项目练习:写一个简单的订单系统,包含事务控制和缓存。

8.4 第四周:综合场景+AI 结合

  • 找真实面经中的场景题,限时解答。
  • 了解 AI 接口调用常见方案(如 HTTP 客户端、消息队列异步处理)。
  • 模拟面试:录音自己回答问题的过程,检查表达是否清晰、逻辑是否连贯。

最重要的一点:面试官更看重你解决问题的思路,而不是死记答案。遇到不会的问题,可以说“这个问题我没遇到过,但我觉得可以从这几个方向排查”,展现出学习能力和逻辑思维。

更多推荐