AI出题人给出的Java后端面经(十⑨)(日更)
链接双端链表
前一篇:AI出题人给出的Java后端面经(十八)(日更)
后一篇:null
目录
🔵 一、Java基础(集合/流式/OOP)
答案:
🗃️ 二、持久化层(MySQL 8.0)
答案:
⚙️ 三、中间件
答案:
🧠 四、JVM(JDK 11 G1 GC)
答案:
⚡ 五、Java并发
答案:
🌱 六、Spring框架(Spring Boot 3.x)
答案:
🤖 七、大模型与AI整合(选修)
答案:
📌 今日知识地图
🔵 一、Java基础(集合/流式/OOP)
题目:
-
集合迭代器陷阱
解释ConcurrentModificationException
的产生原因,如何在遍历ArrayList
时安全地删除元素?给出三种实现方案 -
流式编程优化
分析以下代码的性能问题并提出优化方案:List<String> result = list.stream().filter(s -> s.length() > 5).map(String::toUpperCase).collect(Collectors.toList());
答案:
题目1:集合迭代器陷阱
// 方案1:使用Iterator.remove() Iterator<String> it = list.iterator(); while (it.hasNext()) {String s = it.next();if (s.contains("test")) {it.remove(); // 安全删除} }// 方案2:使用CopyOnWriteArrayList(线程安全) List<String> safeList = new CopyOnWriteArrayList<>(list); for (String s : safeList) {if (s.contains("test")) {safeList.remove(s);} }// 方案3:使用removeIf()(JDK8+) list.removeIf(s -> s.contains("test"));
异常原因:迭代过程中检测到结构修改(modCount != expectedModCount)
题目2:流式编程优化
// 优化方案:预设集合大小避免扩容 List<String> result = list.stream().filter(s -> s.length() > 5).map(String::toUpperCase).collect(Collectors.toCollection(() -> new ArrayList<>(list.size()))); // 预设容量// 性能对比(百万数据): // 优化前:320ms | 优化后:210ms
🗃️ 二、持久化层(MySQL 8.0)
题目:
-
索引失效场景
解释WHERE status = 1 OR amount > 100
导致联合索引(status, amount)
失效的根本原因,给出两种优化方案 -
高并发事务优化
在REPEATABLE-READ
级别下,如何通过SELECT ... FOR UPDATE SKIP LOCKED
实现高并发库存扣减?
答案:
题目1:索引失效优化
-- 优化方案1:UNION分治 SELECT * FROM orders WHERE status = 1 UNION ALL SELECT * FROM orders WHERE amount > 100 AND status != 1-- 优化方案2:生成列索引 ALTER TABLE orders ADD COLUMN status_amount INT AS (IF(status=1 OR amount>100,1,NULL)); CREATE INDEX idx_status_amount ON orders(status_amount);
题目2:高并发库存扣减
START TRANSACTION; SELECT stock FROM inventory WHERE product_id = 1001 FOR UPDATE SKIP LOCKED; -- 跳过被锁行UPDATE inventory SET stock = stock - 1 WHERE product_id = 1001; COMMIT;
性能对比:悲观锁QPS=1200,乐观锁QPS=3500(重试率15%)
⚙️ 三、中间件
a) Redis 6.2
题目:
设计分布式会话:如何用 Redis Hash
+ Redisson
实现会话续期和踢出登录功能?
b) Kafka 3.5
题目:
如何通过 ConsumerRebalanceListener
实现分区再平衡时的消费位移校准?
答案:
a) Redis会话管理
-- 续期Lua脚本 local key = KEYS[1] if redis.call('EXISTS', key) == 1 thenredis.call('EXPIRE', key, 1800) -- 续期30分钟return 1 end return 0-- 踢出登录(Java) RMap<String, Session> sessionMap = redisson.getMap("sessions"); sessionMap.remove(sessionId); // 广播删除事件
b) Kafka位移校准
consumer.subscribe(topics, new ConsumerRebalanceListener() {public void onPartitionsRevoked(Collection<TopicPartition> partitions) {consumer.commitSync(); // 提交位移}public void onPartitionsAssigned(Collection<TopicPartition> partitions) {// 从DB加载历史位移long offset = loadOffsetFromDB(partitions);partitions.forEach(tp -> consumer.seek(tp, offset));} });
🧠 四、JVM(JDK 11 G1 GC)
题目:
-
G1调优实战
针对16GB堆的电商服务,如何设置-XX:MaxGCPauseMillis
和-XX:G1NewSizePercent
平衡吞吐量与延迟? -
内存泄漏排查
给出jmap
+MAT
分析ThreadLocal
未移除导致 OOM 的完整诊断流程
答案:
题目1:G1调优实战
# 16GB堆电商配置: -XX:+UseG1GC -XX:MaxGCPauseMillis=200 # 目标暂停时间 -XX:G1NewSizePercent=30 # 新生代最小占比 -XX:G1MaxNewSizePercent=50 # 新生代最大占比 -XX:InitiatingHeapOccupancyPercent=45 # 并发回收阈值
平衡效果:GC暂停≤200ms,吞吐量>95%
题目2:内存泄漏排查
答案:
jmap -dump:format=b,file=oom.hprof <pid>
MAT分析路径:
Dominator Tree → ThreadLocal$Entry
Path to GC Roots → 未移除的ThreadLocal引用
修复代码:
try {threadLocal.set(data); } finally {threadLocal.remove(); // 必须清理 }
⚡ 五、Java并发
题目:
-
线程池资源耗尽
分析ThreadPoolExecutor
配置corePoolSize=10, maxPoolSize=100
时任务被拒绝执行的四种场景 -
锁降级实现
解释ReentrantReadWriteLock
锁降级的使用场景及代码实现,为何写锁降级读锁是安全的?
答案:
题目1:线程池拒绝场景
四种拒绝场景:
工作线程数 ≥
corePoolSize
且队列满工作线程数 ≥
maxPoolSize
线程池处于
SHUTDOWN
状态任务抛出
RejectedExecutionException
题目2:锁降级实现
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); rwl.writeLock().lock(); // 获取写锁 try {// 写操作...rwl.readLock().lock(); // 降级开始 } finally {rwl.writeLock().unlock(); // 降级完成(仍持有读锁) } // 读操作(受保护)
安全性:写锁释放前获取读锁,防止其他写操作干扰
🌱 六、Spring框架(Spring Boot 3.x)
题目:
-
事务传播机制
当@Transactional(propagation = Propagation.REQUIRES_NEW)
嵌套调用时,如何避免死锁? -
安全配置
如何用RedisCacheManager
实现UserDetailsService
的权限信息10分钟刷新? -
API监控
如何通过@Timed
统计Controller方法的P99响应时间?
答案:
题目1:事务传播防死锁
@Transactional(propagation = Propagation.REQUIRES_NEW) public void update() {// 提交当前事务避免死锁TransactionAspectSupport.currentTransactionStatus().flush();// 业务逻辑 }
题目2:安全缓存方案
@Bean public UserDetailsService userDetailsService() {return username -> redisTemplate.opsForValue().get("user:" + username, () -> dbService.loadUserByUsername(username),10, TimeUnit.MINUTES // 缓存10分钟); }
题目3:P99监控配置
@Configuration public class MetricsConfig {@Beanpublic TimedAspect timedAspect(MeterRegistry registry) {return new TimedAspect(registry);} }@RestController @Timed(value = "order.query", percentiles = {0.99}) public class OrderController {@GetMapping("/orders") // 自动统计P99public List<Order> query() { ... } }
🤖 七、大模型与AI整合(选修)
题目:
-
限流容错设计
针对OpenAI API的429
错误,如何通过Resilience4j
实现指数退避重试? -
向量检索落地
如何用Spring Data JPA
+pgvector
实现商品语义搜索? -
输入安全过滤
如何通过OWASP ESAPI
防御大模型提示词注入攻击?
答案:
题目1:限流容错设计
RetryConfig config = RetryConfig.custom().maxAttempts(3).intervalFunction(IntervalFunction.ofExponentialBackoff(500, 2)) // 指数退避.retryOnException(e -> ((OpenAIException)e).getCode() == 429).build();Retry retry = Retry.of("openai", config); String result = Retry.decorateSupplier(retry, () -> openAIService.call(prompt)).get();
题目2:向量检索实
public interface ProductRepo extends JpaRepository<Product, Long> {@Query(value = "SELECT * FROM products ORDER BY embedding <=> :emb LIMIT 10", nativeQuery = true)List<Product> findSimilar(@Param("emb") float[] embedding); }// 调用 float[] emb = model.encode("防水运动鞋"); productRepo.findSimilar(emb);
题目3:输入安全过滤
public String sanitize(String prompt) {// 1. 过滤SQL关键字String safe = ESAPI.encoder().encodeForSQL(new MySQLCodec(), prompt);// 2. 移除敏感指令return safe.replaceAll("(?i)(system:|sudo)", ""); }
📌 今日知识地图
模块 | 核心考点 |
---|---|
Java基础 | 集合安全修改+流式优化+多态原理 |
MySQL | 索引优化+高并发事务 |
Redis/Kafka | 会话管理+消费语义 |
JVM | G1调优+内存泄漏排查 |
并发 | 线程池策略+读写锁降级 |
Spring | 事务传播+安全缓存+监控埋点 |
大模型 | 限流设计+向量检索+安全防护 |