Q1. HashMap 底层原理?1.7 和 1.8 的区别?
别只背"数组+链表"。面试官想听:1.7 是数组+链表(头插法,多线程可能成环);1.8 改成数组+链表+红黑树(尾插法,链表长度 ≥8 且数组 ≥64 转红黑树)。为什么?因为 hash 碰撞多了,链表 O(n) 查询太慢,红黑树 O(log n)。追问预警:"为什么阈值是 8?"(泊松分布概率分析,概率极低)
Q2. ConcurrentHashMap 1.7 vs 1.8 区别?
1.7:Segment 分段锁(默认 16 段,每段一把锁)。1.8:去掉 Segment,用 CAS + synchronized 锁单个桶(Node)。为什么改?分段锁粒度还是太粗,1.8 锁粒度更细,并发性能更好。
Q3. synchronized 和 Lock 的区别?synchronized 锁升级过程?
Lock(ReentrantLock)更灵活:可中断、可超时、可公平锁。synchronized 是 JVM 层面、自动释放。锁升级:无锁 → 偏向锁 → 轻量级锁(自旋)→ 重量级锁。JDK 15 后偏向锁被废弃了,这个要知道。
Q4. 线程池 7 大参数?拒绝策略有哪些?
核心线程数、最大线程数、空闲存活时间、时间单位、工作队列、线程工厂、拒绝策略。4 种拒绝策略:Abort(抛异常,默认)、CallerRuns(调用者执行)、Discard(丢掉)、DiscardOldest(丢最老的)。实战追问:"阿里为什么禁止用 Executors.newFixedThreadPool?"(队列用的是 LinkedBlockingQueue 无界,OOM 风险)
Q5. JVM 内存模型?堆怎么分代?
堆分新生代(Eden + 2 个 Survivor)和老年代。对象先分 Eden,Minor GC 后存活进 Survivor,年龄够(默认 15)进老年代。大对象直接进老年代。
Q6. CMS 和 G1 的区别?
CMS:老年代收集器,标记-清除,会有碎片。G1:整堆收集,Region 分区,标记-整理+复制,可控停顿时间(-XX:MaxGCPauseMillis)。加分项:提一嘴 ZGC(JDK 11+,着色指针,停顿 <10ms)。
Q7. 怎么排查线上 OOM?
1. 看错误日志确认 OOM 类型(Java heap space / Metaspace / GC overhead)。2. 用 jmap -dump 导出堆快照。3. MAT/Arthas 分析大对象。4. 定位是内存泄漏还是堆太小。
Q8. Spring IOC 和 AOP 的原理?
IOC:BeanFactory → ApplicationContext,通过反射创建 Bean,三级缓存解决循环依赖。AOP:JDK 动态代理(接口)或 CGLIB(类继承)。事务就是 AOP 的典型应用。
Q9. Spring 事务失效的场景?
经典坑题:1. 方法不是 public。2. 自调用(this 调用不走代理)。3. 异常被 catch 了没抛出。4. 抛了检查异常但没配 rollbackFor。5. Bean 没被 Spring 管理。面试官就等你答第 2 和第 3 条。
Q10. SpringBoot 自动装配原理?
@SpringBootApplication → @EnableAutoConfiguration → @Import(AutoConfigurationImportSelector) → 加载 META-INF/spring.factories 里的配置类 → 条件注解(@ConditionalOnClass 等)决定是否生效。
Q11. MySQL 索引为什么用 B+ 树?
对比说:Hash 索引不支持范围查询。B 树每个节点存数据,页大小固定导致每个页存的 key 少,树更高 IO 多。B+ 树非叶子只存 key,叶子存数据并用链表连起来 → 单次 IO 读更多 key(树更矮)+ 范围查询快(遍历叶子链表)。
Q12. 事务隔离级别?MVCC 怎么实现的?
读未提交 → 读已提交 → 可重复读(MySQL 默认)→ 串行化。MVCC:每行有隐藏字段(事务 ID、回滚指针),ReadView 在 RC 级别每次 SELECT 生成新的,RR 级别只第一次生成。所以 RR 能重复读,RC 不能。
Q13. Redis 为什么快?持久化 RDB vs AOF?
快的原因:内存操作、单线程避免锁竞争和上下文切换、IO 多路复用、高效数据结构。RDB:快照,体积小恢复快,但可能丢数据。AOF:追加日志,更安全但体积大。4.0 后支持混合持久化。
Q14. 缓存穿透/击穿/雪崩 + 解决方案?
穿透(查不存在的数据)→ 布隆过滤器 / 缓存空值。击穿(热点 key 过期)→ 互斥锁 / 热点 key 永不过期。雪崩(大量 key 同时过期)→ 随机过期时间 / 多级缓存。三条一字不差背下来,基本必考。
Q15. 设计一个秒杀系统?
分层说:前端限流(按钮置灰)→ 网关限流(令牌桶)→ 应用层:Redis 预扣库存 + 异步 MQ 下单 → DB 最终扣库存。关键点:防止超卖(Redis Lua 原子扣减)、防止恶意刷(验证码+IP 限流)、库存预热、兜底降级。
Q16. 消息队列怎么保证消息不丢?
三个环节:生产者端开 confirm + 重试。Broker 端持久化 + 主从同步。消费者端手动 ack(处理完再确认)。追问:"重复消费怎么办?"(幂等设计,唯一 ID 去重)
⚠️ 避坑提醒
很多人八股背得溜,但一问"你项目里用到过吗?遇到过什么坑?"就哑火了。面试官真正在意的不是你能不能背定义,而是你能不能把知识跟实际场景挂钩。哪怕你只说一句"我们项目用 Redis 做缓存,有一次缓存击穿导致 DB 压力飙升,后来加了热点 key 永不过期",效果也比背 3 分钟定义好 10 倍。
说句掏心窝的:面试不是为了考倒你,是面试官在判断"你来了能不能干活"。基础题别丢分,场景题能说清思路就赢了一半。
祝你面的都会,蒙的都对 ☘️
👉 转发给正在准备 Java 面试的朋友,别让他裸面!