
先回答一个比较现实的问题Java 后端面试准备到底该不该背八股文不少同学对“八股文”三个字有抵触觉得背题没有技术含量。但从面试官的角度看八股文本质上是一套标准化的知识检查清单。它考察的不是记忆力而是你对 Java 核心机制的理解深度。三天的速刷不是让你把题目背下来而是把高频考点的底层逻辑梳理清楚。这样即使面试官换个角度追问你也能沿着原理答出来。这篇文章整理了一份 8 月版本的 Java 后端高频面试题速刷清单按三天时间做了拆分包含核心知识点拆解、源码级面试题分析、手撕代码训练和面试表达建议。无论你是准备暑期实习、校招还是社招跳槽都可以直接照着这个节奏复习。1. Java 后端八股文到底是什么三天怎么安排1.1 面试官考察八股文的真实意图先给八股文做一个不那么贬义的定义。在 Java 后端面试场景里八股文指的是那些高频出现的基础理论题比如 HashMap 底层原理、Spring Bean 生命周期、MySQL 索引失效、Redis 缓存穿透等。这些问题看起来像背诵题实际上每个问题都能往下深挖。举个例子“HashMap 的 put 流程是什么”是第一层继续问“为什么链表转红黑树的阈值是 8”是第二层再继续问“ConcurrentHashMap 在 Java 8 里为什么用 synchronized 而不是分段锁”是第三层。面试官通过这种层层递进的方式判断你是只背了结论还是真正理解设计思想。所以速刷八股文时不要只记答案要把每个高频题背后的“为什么”想明白。1.2 三天的整体复习节奏三天的速刷重点不是追求面面俱到而是把最核心、出现频率最高的知识点拿下。我建议下面这种时间分配方式第 1 天Java 基础、集合框架、并发编程、JVM。这是 Java 后端的根基也是面试必问的四大块。第 2 天Spring、Spring Boot、MySQL、Redis。这是后端开发日常打交道最多的部分主要考察框架理解程度和数据库调优能力。第 3 天消息队列、分布式基础、手撕代码、项目表达。这一天白天刷题、写代码晚上整理项目中的技术亮点把知识点链接到真实项目中。每天复习时长建议 8 到 10 小时上午看原理、画脑图下午刷题验证晚上复盘和补充漏洞。2. 环境准备与工具链2.1 JDK 版本与开发工具刷八股文的过程里很多知识点需要自己写代码验证所以本地环境要先准备好。版本不需要追求最新关键是稳定并且和你目标公司的技术栈尽量一致。目前大多数中小型互联网公司仍以 Java 8 和 Java 11 为主部分新项目开始使用 Java 17。建议本地安装 JDK 8 和 JDK 17 两个版本遇到版本特性题目时可以切换验证。开发工具方面IDEA 社区版或 Ultimate 版都够用。需要配置 Maven 或 Gradle用于创建小型验证工程。如果你还没有装环境可以参考官方文档安装这里不推荐特定安装包。2.2 速刷阶段的资料准备三天时间比较紧张不建议从头到尾啃书。我建议准备下面几类资料一份高频面试题清单按 Java 基础、集合、并发、JVM、Spring、MySQL、Redis、MQ、分布式分类。一份源码阅读笔记重点看 HashMap、ConcurrentHashMap、ArrayList、Spring 容器相关源码。一个 GitHub 仓库或者本地笔记目录用来记录你自己的答案版本。一个在线 SQL 练习平台或本地 MySQL 环境用来验证索引、事务、锁相关的问题。一句话总结资料可以多但必须建立自己的答案体系而不是收藏了就等于复习了。3. 核心高频知识点拆解按专题逐个击破3.1 Java 基础与集合框架集合框架是 Java 面试的必考区域优先级最高。常见问题包括ArrayList 和 LinkedList 的区别、扩容机制。HashMap 的数据结构、put 和 get 流程、扩容时机、线程安全问题。ConcurrentHashMap 的锁机制演进。HashSet 如何实现去重。Iterator 和 ListIterator 的区别。这里我先梳理几个最容易在面试中暴露短板的地方。ArrayList 的默认容量是 10扩容时每次增加原来的 1.5 倍。这里经常被追问的是为什么是 1.5 倍而不是 2 倍背后涉及空间和时间的权衡扩容太频繁会导致拷贝次数增加扩得太大又会浪费内存。HashMap 在 Java 8 中的结构是数组加链表加红黑树。当链表长度超过 8 并且数组长度大于等于 64 时链表会转换成红黑树。很多同学只记住了阈值 8不理解为什么要选 8。这其实是基于泊松分布的统计结果在随机哈希函数下链表长度达到 8 的概率极低选 8 是为了在时间和空间之间找一个平衡点。ConcurrentHashMap 在 Java 7 里用的是分段锁Java 8 改成了 CAS 加 synchronized 锁住数组的首个节点。你可以这样理解JDK 8 的锁粒度更细只有发生哈希冲突的桶才会被锁住并发度更高。3.2 Java 并发编程并发编程是后端面试的高区分度区域考察的是你有没有处理过高并发场景的思维。高频考点集中在synchronized 和 ReentrantLock 的区别。volatile 关键字的作用和局限性。ThreadLocal 的原理与内存泄漏问题。线程池的核心参数、执行流程、拒绝策略。乐观锁和悲观锁的区别。CAS 机制与 ABA 问题。先说 volatile。volatile 保证可见性和有序性但不保证原子性。它通过内存屏障禁止指令重排序同时让线程写回主内存时其他线程立即可见。但 count 这种复合操作volatile 解决不了原子性问题。再说线程池。面试时经常让手写一个线程池配置核心参数有七个核心线程数、最大线程数、空闲存活时间、时间单位、任务队列、线程工厂、拒绝策略。执行流程可以理解为新任务来了先看核心线程是否满没满就创建线程执行满了就进队列队列满了就判断是否超过最大线程数还不够就触发拒绝策略。这里有个非常容易被追问的点CPU 密集型和 IO 密集型的核心线程数怎么设置。CPU 密集型建议设置为 CPU 核数加一IO 密集型可以设置为核心数乘以二或者用公式“核心线程数等于 CPU 核数除以一减阻塞系数”。面试时重点说清楚思路不要死背数字。3.3 JVM 内存与垃圾回收JVM 相关题目这几年出现频率一直很高尤其是内存区域划分、垃圾收集器、类加载机制和 OOM 排查。必背内容可以整理成下面几个题目JVM 运行时数据区有哪些堆、虚拟机栈、本地方法栈、方法区元空间、程序计数器。哪些区域是线程共享的哪些是线程私有的。常用的垃圾收集器有哪些Serial、Parallel、CMS、G1、ZGC。如何判断对象可以被回收引用计数法和可达性分析。类加载过程有哪几步加载、验证、准备、解析、初始化。双亲委派模型是什么样的为什么要这么设计。这里特别提醒一下直接内存不在运行时数据区里但它也可能导致 OOM。NIO 使用 DirectByteBuffer 时分配的是堆外内存如果忘记释放就会出现“java.lang.OutOfMemoryError: Direct buffer memory”这类问题。这也是面试里很常见的场景题。关于 G1 和 CMS 的区别要能说清楚CMS 是基于标记清除算法会产生内存碎片G1 是基于 Region 划分可以做到可预测的停顿时间。如果你投的是高并发团队还会被追问 ZGC 为什么延迟低核心在于染色指针和读屏障这在速刷阶段可以放到第二天了解。3.4 Spring 核心机制Spring 是 Java 后端开发的事实标准几乎每一面都会问到。高优先级题目包括什么是 IOC 和 AOP。Bean 的生命周期。Spring 如何解决循环依赖。Spring 事务的传播行为。Spring Boot 自动配置原理。Autowired 和 Resource 的区别。Bean 的生命周期可以分阶段记忆实例化、属性赋值、初始化、销毁。在初始化前后有各种 Aware 接口和 BeanPostProcessor 扩展点。回答时建议按下面流程说Spring 扫描到 BeanDefinition然后通过反射创建实例接着进行属性填充再执行 Aware 接口回调然后调用 BeanPostProcessor 的 postProcessBeforeInitialization执行 InitializingBean 或 init-method最后调用 postProcessAfterInitialization。循环依赖是 Spring 面试的经典难题。Spring 通过三级缓存解决单例 Bean 的循环依赖一级缓存存完整对象二级缓存存早期暴露的半成品对象三级缓存存 ObjectFactory。构造器注入的循环依赖无法通过三级缓存解决只能加 Lazy 或者改设计。面试官问到这里大概率是想看你对 IOC 容器的理解深度。事务传播行为中最常用的是 REQUIRED 和 REQUIRED_NEW。REQUIRED 表示如果当前存在事务则加入不存在则新建REQUIRED_NEW 永远开启一个新事务。特别要注意Spring 事务默认只在 RuntimeException 时回滚如果方法抛出受检异常事务默认是提交的需要通过 rollbackFor 指定回滚异常类型。3.5 MySQL 与索引优化MySQL 是后端面试中决定你能否通过技术面的关键。数据库部分的题可以刷得比较细因为面试官最容易从这个方向判断你有没有真实项目经验。高频考点包括InnoDB 和 MyISAM 的区别。聚簇索引、非聚簇索引、覆盖索引、回表。索引失效的常见场景。事务的四大特性和隔离级别。MVCC 的实现原理。当前读和快照读的区别。间隙锁、临键锁、Record Lock。先看索引。InnoDB 的聚簇索引就是主键索引叶子节点保存整行数据非聚簇索引的叶子节点保存主键值查询时需要通过主键再回表查询。如果查询列全部在索引中就不需要回表这叫覆盖索引。理解这条链路就可以回答大部分索引问题。索引失效是面试场景题的高发区。最常见的场景包括对索引列使用函数或计算隐式类型转换like 前缀模糊查询联合索引不满足最左前缀原则使用 or 连接非索引列。比如对 phone 字段建了索引但查询条件写成 where phone 13812345678如果 phone 是 varchar 类型而传入数字MySQL 会做隐式转换索引就会失效。MVCC 是 InnoDB 实现可重复读的关键机制。它通过隐藏字段、undo log 和 ReadView 实现多版本并发控制。在可重复读隔离级别下事务第一次执行查询时生成 ReadView之后复用同一个 ReadView所以解决了幻读问题注意这里解决的是快照读的幻读当前读仍然需要通过临键锁或串行化来防止幻读。3.6 Redis 缓存Redis 在 Java 后端项目里几乎是标配。面试考点相对集中突击性价比很高。必背内容包括五种基础数据类型和底层编码结构。持久化机制 RDB 和 AOF。过期删除策略和内存淘汰策略。缓存穿透、缓存击穿、缓存雪崩的区别和解决方案。Redis 分布式锁的实现和可能的问题。主从复制和哨兵机制。缓存穿透是指查询一个不存在的数据请求直接打到数据库。常见解决办法是缓存空值或者使用布隆过滤器。缓存击穿是指热点 key 过期瞬间大量请求绕过缓存解决方案有互斥锁和逻辑过期。缓存雪崩是指大量 key 同时过期或者 Redis 实例宕机导致请求全部打到数据库解决方案包括过期时间加随机值、集群高可用、限流降级。分布式锁这块需要说清楚Redis 实现分布式锁通常用 SET NX EX 命令但在极端情况下会存在锁误删问题和锁过期业务未完成问题。正确的扩展方案是使用 Redisson 的看门狗机制自动续期。如果公司对一致性要求非常高可以考虑 ZooKeeper 或 etcd 实现分布式锁面试中主动说出这个权衡会很加分。3.7 消息队列与分布式基础消息队列部分的首选复习对象是 Kafka因为大厂用得最多。热点题目包括Kafka 的基本架构Producer、Consumer、Broker、Topic、Partition、Consumer Group。Kafka 如何保证消息顺序。Kafka 如何保证消息不丢失和不重复消费。如何提高 Kafka 的消费性能。零拷贝在 Kafka 中的应用。关于消息不丢失可以从生产者、Broker、消费者三个端分别说。生产者端使用 acksall 并开启重试Broker 端设置副本数大于一并且 min.insync.replicas 满足要求消费者端关闭自动提交处理完业务后再手动提交偏移量。消息不重复则需要消费端做幂等设计比如用唯一业务号去重表或者 Redis setnx 判断是否处理过。这里可以补充一句Kafka 自带的幂等性只能解决生产者发送消息的重复问题不能完全替代消费端的幂等设计。分布式部分主要看 CAP 理论和 BASE 理论以及分布式事务的几种常见方案二阶段提交、TCC、本地消息表、最大努力通知。这部分的复习策略是掌握定义和适用场景然后结合项目说明你用到了哪些柔性方案。4. 高频面试题实战拆解从答案到追问4.1 HashMap 的 put 流程从源码角度完整回答先看一个简单版本的代码定位// 文件路径示例代码用于理解 HashMap put 流程 MapString, String map new HashMap(); map.put(name, csdn);面试时建议按下面这条思路回答第一步计算 key 的 hash 值通过扰动函数让高位也参与运算降低哈希冲突概率。第二步判断哈希表数组是否为空为空则触发 resize 初始化默认容量是 16。第三步根据 hash 计算数组下标算法是 (n - 1) hash。如果该位置为空直接创建新节点放入。第四步如果该位置已有节点判断 key 是否相同。相同则覆盖 value。第五步如果不相同判断当前节点是否为红黑树节点是就按红黑树的逻辑插入。第六步如果是链表节点遍历链表找 key。没找到则追加到链表尾部然后判断链表长度是否大于等于 8。同时还需要满足数组长度大于等于 64否则先扩容而不是转红黑树。第七步插入完成后检查 size 是否超过 threshold超过则扩容扩容大小是原来的两倍。顺着这条线面试官很可能追问为什么插入后是尾插法。Java 8 之前头插法在并发扩容时可能出现循环链表Java 8 改成尾插法之后虽然不能完全解决线程安全问题但至少避免了死循环。4.2 Spring 循环依赖为什么能解决下面是一个典型的生产者消费者示例代码。可以先用代码理解依赖关系// 文件路径示例代码演示循环依赖场景 Component public class AService { Autowired private BService bService; } Component public class BService { Autowired private AService aService; }面试时可以这样组织回答。Spring 创建 A 时发现 A 依赖 B于是先去创建 B。创建 B 时B 又依赖 A。如果这时候 A 还没有完全创建好B 就拿不到 A。Spring 的解决办法是在 A 完成属性填充之前先把自己暴露到一个 ObjectFactory 中这个工厂对象放在三级缓存里。B 创建时可以提前通过工厂获取 A 的早期引用完成注入。需要注意只有单例模式并且是 setter 注入或字段注入时Spring 能通过三级缓存解决循环依赖。构造器注入不行因为构造器执行时对象还没有实例化完成无法提前暴露。4.3 MySQL 索引失效场景与验证思路索引失效的知识点很多面试时不要只罗列现象最好能给出一个验证方法。下面是一个建索引和测试的 SQL 示例思路-- 示例验证索引是否生效 CREATE TABLE t_user ( id BIGINT PRIMARY KEY AUTO_INCREMENT, phone VARCHAR(20), name VARCHAR(50), age INT, KEY idx_phone (phone), KEY idx_name_age (name, age) ); -- 场景1对索引列使用函数索引失效 EXPLAIN SELECT * FROM t_user WHERE CONCAT(phone, ) 13812345678; -- 场景2隐式类型转换varchar 列传入数值索引失效 EXPLAIN SELECT * FROM t_user WHERE phone 13812345678; -- 场景3联合索引不遵循最左前缀 EXPLAIN SELECT * FROM t_user WHERE age 18;回答问题时可以这么说判断索引是否失效最直接的方法是使用 EXPLAIN 命令看 type 字段和 key 字段。如果 type 从 ref 变成 ALL说明走了全表扫描。对于索引列使用函数优化器无法使用索引因为在索引树上无法直接计算函数结果。4.4 Redis 缓存雪崩的解决方案缓存雪崩的典型场景是大量缓存 key 在同一时间段集中过期或者 Redis 实例不可用导致所有请求穿透到数据库。结合项目说一下方案优先级比较自然第一给缓存过期时间加一个随机值让过期时间分散开。第二对于热点数据可以不设置过期时间由后台任务主动更新或者使用逻辑过期方案。第三查询逻辑加互斥锁同一时间只允许一个请求去数据库加载数据其他请求等待缓存回填。第四从系统高可用角度Redis 要做主从加哨兵或集群部署核心接口还要配置限流和降级。回到面试表达上尽量不要说“我们系统用了互斥锁就解决了”而是说清楚你判断问题的依据和每一步的取舍。5. 手撕代码训练清单第三天下午建议集中练手撕代码。下面这组题是后端面试里出现频率最高、代码量适中的题目。5.1 单例模式单例模式几乎每次面试都会出现至少要能写出双检锁版本。// 文件路径示例代码双检锁单例 public class Singleton { private static volatile Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance null) { synchronized (Singleton.class) { if (instance null) { instance new Singleton(); } } } return instance; } }这个代码里的 volatile 不能去掉它禁止了 instance new Singleton() 这一步的指令重排序。如果去掉另一个线程可能拿到一个未初始化完成的对象。还可以补充一个静态内部类实现方式说明它既支持懒加载又不需要加锁原理是利用了类加载机制保证线程安全。5.2 生产者消费者模型生产者消费者模型考察线程通信的基本功。用 BlockingQueue 实现是最直观的方式。// 文件路径示例代码BlockingQueue 实现生产者消费者 import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; public class ProducerConsumerDemo { public static void main(String[] args) { BlockingQueueInteger queue new ArrayBlockingQueue(10); Thread producer new Thread(() - { int i 0; while (true) { try { queue.put(i); System.out.println(生产 i); i; Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } }); Thread consumer new Thread(() - { while (true) { try { Integer value queue.take(); System.out.println(消费 value); Thread.sleep(2000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } }); producer.start(); consumer.start(); } }这道题的加分点在细节ArrayBlockingQueue 底层是 ReentrantLock 加两个 Conditionput 和 take 都支持阻塞和响应中断使用 InterruptedException 时要把中断状态传递出去。5.3 链表反转与二分查找链表反转是算法题里的常客二分查找则能以很多变体出现。// 文件路径示例代码链表反转 public class ListNode { int val; ListNode next; ListNode(int val) { this.val val; } } public ListNode reverseList(ListNode head) { ListNode prev null; ListNode curr head; while (curr ! null) { ListNode nextTemp curr.next; curr.next prev; prev curr; curr nextTemp; } return prev; }// 文件路径示例代码二分查找 public int binarySearch(int[] nums, int target) { int left 0; int right nums.length - 1; while (left right) { int mid left (right - left) / 2; if (nums[mid] target) { return mid; } else if (nums[mid] target) { left mid 1; } else { right mid - 1; } } return -1; }写二分查找时注意两个细节用 left (right - left) / 2 而不是 (left right) / 2避免整数溢出循环条件、边界更新的方式要和返回统一。出现死循环或越界通常是 left 和 right 的更新逻辑不一致导致的。6. 面试回答技巧与常见问题6.1 把八股文转化为项目经验很多同学背了很多技术点但面试时总是被评价为“没有项目深度”。常见的问题是面试官问“你们项目里 Redis 用来做什么”回答只有一句“做缓存”。这就等于把送分题变成了送命题。正确的做法是用一个模板组织答案项目背景加业务挑战加技术方案加落地效果。举个例子如果项目里使用 Redis 缓存热点数据可以这样展开订单详情页的 QPS 比较高数据库压力大所以把热点商品数据缓存到 Redis。缓存结构选择了 Hash因为需要频繁更新某个字段不需要整体序列化。过期时间设定为 30 分钟加随机值防止集中失效。同时在大促期间通过逻辑过期解决热点 key 突然失效的问题。这样回答就能把缓存穿透、击穿、雪崩的知识点全部串起来。6.2 遇到不会的题怎么处理面试中遇到完全陌生的题目不推荐直接说“不会”也不推荐硬答。比较自然的处理方式是先向面试官确认问题背景再说自己的初步理解最后表达可以现场思考。比如面试官问“你们怎么设计一个限流方案”如果你对具体框架不熟可以回答限流常见实现有固定窗口、滑动窗口、漏桶算法和令牌桶算法我了解令牌桶算法它允许一定的突发流量适合大部分接口场景。如果在生产环境落地我会优先使用成熟组件比如 Resilience4j 或 Sentinel而不是自己实现。这样回答即使你对方案细节不熟悉也展示了自己的知识边界和解决问题的思路。6.3 速刷阶段的心态管理三天速刷信息密度很大不可能每个知识点都完全背下来。建议把题目按优先级分成三档。第一档是基础题比如 HashMap 原理、Spring 核心特性、MySQL 索引、Redis 数据结构这些必须滚瓜烂熟。第二档是进阶题比如 JVM 调优、Kafka 消息可靠性、分布式事务需要理解原理至少能说出来龙去脉。第三档是补充题比如具体框架源码细节、算法变体有余力再刷。遇到不会的题记录下来当天晚上统一复盘。第二天早上再快速过一遍前一天错题比单纯刷新题效果好得多。7. 复习策略与长期规划7.1 三天之后建议继续深入的方向三天速刷适合在短期内快速恢复知识体系但如果你想进入面试通过率更高的梯队建议之后在下面几个方向继续投入第一个方向是源码阅读。比如把 Spring 容器的 refresh 方法完整读一遍理解 Bean 从扫描到注册再到初始化的全过程再读一遍 MyBatis 的插件机制理解动态代理在框架中的实际应用。这些源码知识是让面试回答与众不同的关键。第二个方向是项目深挖。准备一个自己最有把握的项目画出架构图梳理每个技术点解决的问题然后把项目里的技术选型和参考方案对比想清楚为什么不用其他方案。第三个方向是真实性能问题排查。可以自己搭建一个小系统制造一次 CPU 飙升或 OOM用 top、jstack、jmap 这些工具实际排查一遍。有排查经验的人面试时的表达会更扎实。7.2 八股文是入场券工程能力才是分水岭三天速刷的目标是让你在短时间内把高频考点覆盖到顺利通过面试筛选。但真正进入团队之后面试官会关注你的代码习惯、问题排查能力和交付质量。所以复习的时候不要让八股文变成唯一的依靠。每背一个知识点都尽量和真实场景挂钩。比如 MySQL 走索引能带来多大的性能提升缓存和数据库的一致性问题如何解决线程池参数在项目里怎么确定。这些内容没有标准答案却最能体现你的后端综合能力。这篇文章整理的题目范围是按大多数 Java 后端岗位的高频面试题来确定的。如果你时间比较紧优先保证 HashMap、并发、Spring、MySQL、Redis 这几块不出错再逐步拓展到 JVM、消息队列和分布式。复习过程中建议用 Markdown 给自己整理一份面试笔记每条知识点都写下“自己的话版本”这样比直接把网上的答案复制下来更有用。后面面试和复盘时这份笔记会比收藏夹里的资料更有价值。