AI出题人给出的Java后端面经(一)(日更)
链接双端链表:
前一篇:null
目录
题目: 描述 Redis 缓存穿透和缓存击穿的现象及区别。针对缓存击穿(某个热点Key过期瞬间大量请求压垮数据库),给出至少两种有效的解决方案并简述原理。
题目: JVM 调优中经常调整堆内存参数 (-Xms, -Xmx, -Xmn)。请问:
1.-XX:NewRatio 和 -XX:SurvivorRatio 这两个参数分别控制什么?
2.假设一个系统对象生命周期特征为“朝生夕死”,为了减少 Full GC 频率,应如何调整新生代和老年代的比例?为什么?
题目: CompletableFuture 是 Java 8 引入的强大异步编程工具。请写出代码片段,实现以下需求:
题目: Spring 声明式事务管理中,传播行为 Propagation.REQUIRES_NEW 和 Propagation.NESTED 的主要区别是什么?请结合以下场景说明:
🔵 一、Java 基础
题目: 解释 HashMap 在 JDK 1.8 中的底层数据结构(数组+链表/红黑树),并详细说明 put(key, value) 方法的工作流程(包括哈希计算、解决哈希冲突、链表转红黑树的条件等)。
答案:
HashMapJDK 1.8 底层结构:数组 + 链表/红黑树
put()流程:
哈希计算:
key.hashCode()高16位与低16位异或(扰动函数),减少哈希冲突。定位桶:
(n - 1) & hash计算数组下标。解决冲突:
若桶为空,直接插入新节点。
若桶为链表,遍历链表:
存在相同
key则覆盖值。否则尾部插入新节点,若链表长度 ≥8 且数组长度 ≥64,链表转红黑树。
扩容机制:
当元素数 >
容量 × 负载因子(默认0.75)时,数组扩容为2倍。重新计算节点位置(原位置 或 原位置 + 旧容量)。
⚠️ 链表转树条件:链表长度 ≥8 且 数组长度 ≥64(否则优先扩容)。
🗃️ 二、MySQL
题目: 什么是 MySQL 中的“间隙锁”(Gap Lock)?它主要解决什么问题?请结合 SELECT ... FOR UPDATE 语句和 REPEATABLE READ 隔离级别举例说明一个可能产生间隙锁的场景。
答案:
间隙锁 (Gap Lock):
作用:锁定索引记录之间的间隙(解决幻读),仅存在于
REPEATABLE READ隔离级别。场景示例:
-- 表t有索引age: [10, 20, 30] BEGIN; SELECT * FROM t WHERE age = 25 FOR UPDATE; -- 锁定(20, 30)的间隙此时其他事务无法插入
age ∈ (20, 30)的记录(如插入25)。关键点:间隙锁保护的是“范围”,不是具体记录。
⚙️ 三、中间件
a) 消息队列 (Kafka)
题目: Kafka 为了保证高可用性和数据不丢失,采用了副本(Replica)机制。请解释 Kafka 中 ISR (In-Sync Replicas) 列表的含义和作用。当 Leader 副本宕机时,如何从 ISR 中选举新的 Leader?
答案
ISR (In-Sync Replicas):与 Leader 数据同步的副本集合(含 Leader)。
选举新 Leader:
Controller 监控 Broker 状态。
Leader 宕机后,Controller 从 ISR 中选择第一个可用副本作为新 Leader。
若 ISR 为空,根据
unclean.leader.election.enable配置决定是否允许非 ISR 副本当选(可能丢失数据)。
b) Redis
题目: 描述 Redis 缓存穿透和缓存击穿的现象及区别。针对缓存击穿(某个热点Key过期瞬间大量请求压垮数据库),给出至少两种有效的解决方案并简述原理。
答案:
缓存击穿:热点 Key 过期瞬间,大量请求直接击穿到数据库。
解决方案:
互斥锁 (Mutex Lock):
请求 Key 失效时,用
SETNX竞争锁,获取锁的线程查库并重建缓存,其他线程等待。逻辑过期时间:
Value 中存储实际过期时间字段。
发现数据逻辑过期时,异步线程更新缓存,当前线程返回旧数据。
永不过期 + 后台更新:
Key 不设 TTL,后台定时更新缓存。
穿透 vs 击穿:穿透是查询不存在的数据,击穿是热点Key失效。
🧠 四、JVM
题目: JVM 调优中经常调整堆内存参数 (-Xms, -Xmx, -Xmn)。请问:
1.-XX:NewRatio 和 -XX:SurvivorRatio 这两个参数分别控制什么?
答案:
-XX:NewRatio=2:老年代 / 新生代 = 2:1(默认值)。
-XX:SurvivorRatio=8:Eden / Survivor = 8:1(每个 Survivor 占新生代的1/10)。
2.假设一个系统对象生命周期特征为“朝生夕死”,为了减少 Full GC 频率,应如何调整新生代和老年代的比例?为什么?
答案:
优化“朝生夕死”场景:增大新生代(如
-XX:NewRatio=1,使新生代占堆的50%)。原因:对象在新生代被回收,减少进入老年代的对象数量,从而降低 Full GC 频率。
⚡ 五、Java 并发
题目: CompletableFuture 是 Java 8 引入的强大异步编程工具。请写出代码片段,实现以下需求:
-
异步执行任务A (
supplyAsync(() -> "Hello")) -
任务A完成后,将其结果与另一个异步任务B (
supplyAsync(() -> " World")) 的结果拼接。 -
拼接完成后,将结果转换为大写 (
thenApply(String::toUpperCase))。 -
最终消费结果并打印 (
thenAccept(System.out::println))。
答案:
CompletableFuture<String> futureA = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> futureB = CompletableFuture.supplyAsync(() -> " World"); futureA.thenCombine(futureB, (a, b) -> a + b) // 拼接结果 .thenApply(String::toUpperCase) // 转大写 .thenAccept(System.out::println); // 打印 "HELLO WORLD"关键点:
thenCombine用于合并两个独立异步任务的结果。
🌱 六、Spring 框架
题目: Spring 声明式事务管理中,传播行为 Propagation.REQUIRES_NEW 和 Propagation.NESTED 的主要区别是什么?请结合以下场景说明:
方法
outerMethod开启了事务,它内部调用了innerMethod。如果innerMethod配置了REQUIRES_NEW/NESTED传播行为,当innerMethod内部发生异常并被outerMethod捕获处理时,innerMethod的事务和outerMethod的事务会如何回滚?
答案:
传播行为 事务特性 回滚场景(当 innerMethod异常被捕获时)REQUIRES_NEW 挂起当前事务,创建独立新事务 innerMethod事务回滚,outerMethod事务不受影响NESTED 在当前事务中创建嵌套子事务(Savepoint机制) innerMethod回滚到 Savepoint,outerMethod事务可选择提交或回滚场景总结:
REQUIRES_NEW:内外事务完全独立(类似新线程)。
NESTED:内嵌事务是外部事务的一部分(外部事务回滚会导致嵌套事务回滚)。
✅ 今日重点知识:
-
HashMap链表转红黑树的精确条件。 -
MySQL 间隙锁的触发场景。
-
Redis 缓存击穿的两种解决方案(锁 vs 逻辑过期)。
-
CompletableFuture链式调用写法。 -
REQUIRES_NEW与NESTED的事务边界差异。
更多推荐
所有评论(0)