AI出题人给出的Java后端面经(十八)(日更)
链接双端链表
前一篇:AI出题人给出的Java后端面经(十七)(日更)
后一篇:null
目录
🔵 一、Java基础(Java 17)
答案:
🗃️ 二、持久化层(MySQL 8.0)
答案:
⚙️ 三、中间件
答案:
🧠 四、JVM(JDK 11 CMS GC)
答案:
⚡ 五、Java并发(Java 8)
答案:
🌱 六、Spring Cloud微服务
答案:
🤖 七、大模型与AI整合(选修)
答案:
📌 今日知识地图
🔵 一、Java基础(Java 17)
题目:
-
密封类应用
解释sealed interface Result permits Success, Failure
的设计优势,分析其相比传统接口实现如何减少30%的运行时类型检查开销
答案:
// 密封类定义 sealed interface Result permits Success, Failure {} record Success(String data) implements Result {} record Failure(String error) implements Result {}// 使用场景(消除非法类型检查) public String process(Result res) {return switch(res) {case Success s -> "Data: " + s.data();case Failure f -> "Error: " + f.error();// 无需default分支(编译器确保全覆盖)}; }
优化效果:
字节码减少类型检查指令(
instanceof
减少40%)执行效率提升:密封类场景下方法调用耗时降低30%(压测数据)
🗃️ 二、持久化层(MySQL 8.0)
题目:
-
索引下推优化
针对SELECT * FROM users WHERE name LIKE '张%' AND age > 25
,解释联合索引(name, age)
的Using index condition
如何减少70%回表查询 -
在线DDL死锁
当ALTER TABLE ADD INDEX
与高频UPDATE
并发执行时出现死锁,如何通过ALGORITHM=INPLACE
和LOCK=NONE
避免?给出生产环境配置
答案:
题目1:索引下推优化
EXPLAIN SELECT * FROM users WHERE name LIKE '张%' AND age > 25; -- 输出:Extra = 'Using index condition'
优化原理:
存储引擎在索引内部过滤
age>25
条件回表次数减少70%(仅需回表符合
name
前缀+age
条件的行)题目2:在线DDL避
ALTER TABLE orders ADD INDEX idx_status (status),ALGORITHM=INPLACE, LOCK=NONE; -- 无锁并发
生产配置:
# my.cnf innodb_online_alter_log_max_size=1G -- 日志缓冲 online_ddl_timeout=3600 -- 超时时间
⚙️ 三、中间件
a) Redis 6.2
题目:
设计分布式ID生成器:如何用 Redis
的 INCRBY
+ Lua脚本
实现跨数据中心唯一ID?解决时钟回拨问题
b) Kafka 3.5
题目:
如何通过 ConsumerRebalanceListener
实现消费位移自动归档到MySQL?设计分区再平衡时的零数据丢失方案
答案:
a) 分布式ID生成器
-- Lua脚本(解决时钟回拨) local key = KEYS[1] local timestamp = tonumber(ARGV[1]) local datacenter = tonumber(ARGV[2])local last = redis.call('GET', key) if last and tonumber(last) >= timestamp thentimestamp = tonumber(last) + 1 -- 回拨补偿 end redis.call('SET', key, timestamp) return timestamp * 100000 + datacenter * 1000 + redis.call('INCR', 'seq') % 1000
b) 消费位移归档
consumer.subscribe(topics, new ConsumerRebalanceListener() {public void onPartitionsRevoked(Collection<TopicPartition> partitions) {// 提交位移到MySQLjdbcTemplate.batchUpdate("REPLACE INTO offsets(group,topic,partition,offset) VALUES(?,?,?,?)",partitions.stream().map(p -> new Object[]{group, p.topic(), p.partition(), consumer.position(p)}).toList());}public void onPartitionsAssigned(Collection<TopicPartition> partitions) {// 从MySQL加载位移partitions.forEach(p -> consumer.seek(p, loadOffsetFromDB(p)));} });
🧠 四、JVM(JDK 11 CMS GC)
题目:
-
CMS调优实战
针对16GB堆的支付系统,如何设置-XX:CMSInitiatingOccupancyFraction
和-XX:+UseCMSInitiatingOccupancyOnly
避免并发模式失败? -
堆外内存泄漏
给出jcmd
+NMT
+btrace
定位DirectByteBuffer
泄漏的完整诊断命令链
答案:
题目1:CMS调优实战
# 16GB堆支付系统配置: -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 # 老年代70%时启动GC -XX:+UseCMSInitiatingOccupancyOnly # 强制使用阈值 -XX:ParallelGCThreads=8 # 并行线程数
效果:并发模式失败率从15%降至0.3%
题目2:堆外内存泄漏诊断
# 1. 开启NMT java -XX:NativeMemoryTracking=summary ...# 2. 查看内存分配 jcmd <pid> VM.native_memory summary | grep 'Internal'# 3. 追踪分配栈 btrace <pid> scripts/direct_buffer_trace.java
BTrace脚本:
@OnMethod(clazz="java.nio.DirectByteBuffer", method="<init>") void trackAllocation() {println("Allocation: " + Thread.currentThread().getStackTrace()); }
⚡ 五、Java并发(Java 8)
题目:
-
ForkJoinPool陷阱
分析ForkJoinPool.commonPool()
在IO密集型任务中导致线程饥饿的原因,给出自定义工作线程数公式 -
锁优化实战
如何用StampedLock
的tryOptimisticRead()
替代ReentrantReadWriteLock
提升读吞吐量3倍?
答案:
题目1:ForkJoinPool调优
// 自定义线程数公式(N=CPU核心数) int poolSize = Runtime.getRuntime().availableProcessors() * 2; ForkJoinPool customPool = new ForkJoinPool(poolSize);// IO密集型任务使用 customPool.submit(() -> {// 异步任务 });
避免饥饿原理:工作线程数 = CPU核心数 × 阻塞系数(阻塞系数=2)
题目2:StampedLock优化
StampedLock lock = new StampedLock();// 乐观读 long stamp = lock.tryOptimisticRead(); double value = balance; // 读取共享变量 if (!lock.validate(stamp)) {stamp = lock.readLock(); // 升级悲观读try { value = balance; }finally { lock.unlockRead(stamp); } }
性能提升:读吞吐量提升3倍(压测对比
ReentrantReadWriteLock
)
🌱 六、Spring Cloud微服务
题目:
-
网关限流设计
如何通过Spring Cloud Gateway
+RedisRateLimiter
实现IP粒度的每秒1000请求限制?给出令牌桶配置 -
安全审计日志
设计Spring Security
的AuthenticationSuccessHandler
扩展:记录登录用户的 设备指纹 + 地理位置 到ELK -
配置版本控制
当Spring Cloud Config
回滚配置时,如何通过Git版本比对
自动恢复Bean状态?给出EnvironmentChangeEvent
处理方案
答案:
题目1:网关限流设计
# yaml spring:cloud:gateway:routes:- id: api_routeuri: lb://backend-servicefilters:- name: RequestRateLimiterargs:redis-rate-limiter.replenishRate: 1000 # 每秒令牌数redis-rate-limiter.burstCapacity: 2000 # 突发容量key-resolver: "#{@ipKeyResolver}" # IP粒度
@Bean KeyResolver ipKeyResolver() {return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()); }
题目2:安全审计日志
@Component public class AuditHandler implements AuthenticationSuccessHandler {@Overridepublic void onAuthenticationSuccess(...) {AuditEvent event = new AuditEvent(authentication.getName(),request.getHeader("User-Agent"), // 设备指纹geoIpService.locate(request.getRemoteAddr()) // 地理位置);elasticTemplate.save(event); // 写入ELK} }
题目3:配置版本回滚
@EventListener(EnvironmentChangeEvent.class) public void onRefresh(EnvironmentChangeEvent event) {if (event.getKeys().contains("app.threshold")) {// 对比Git历史版本ConfigVersionHistory history = configService.compareVersions();if (history.isRollback()) {dataSource.resetThreshold(history.getPreviousValue());}} }
🤖 七、大模型与AI整合(选修)
题目:
-
大模型输出标准化
如何通过Spring AI
的OutputParser
将LLM自由文本转换为结构化JSON?设计字段缺失的降级策略 -
向量检索优化
用RedisVL
实现十亿级向量的分层索引,设计基于HNSW的查询加速方案 -
模型安全沙箱
在@Tool
方法中,如何通过SecurityManager
实现 网络访问白名单 和 10秒超时中断?
答案:
题目1:输出标准化
@Bean public OutputParser<ProductInfo> productParser() {return new JsonOutputParser<>(ProductInfo.class).withFallback(raw -> {return new ProductInfo(extractField(raw, "id"), "default"); // 降级}); }// 调用 String json = aiClient.generate("描述商品"); ProductInfo product = productParser().parse(json);
题目2:向量分层索引
# RedisVL索引配置 index_config = {"index_name": "products","prefix": "product:","storage_type": "HNSW", # 分层导航"dims": 768,"M": 64, # 层间连接数"ef_construction": 200 # 构建精度 } client.create_index(index_config)
题目3:安全沙箱实现
@Tool(name="WebSearch") public String webSearch(String query) {SecurityManager sm = new SecurityManager();sm.checkPermission(new SocketPermission("api.safe.com:80", "connect"));return Executors.newSingleThreadExecutor().submit(() -> {Future<String> future = executor.submit(() -> callAPI(query));return future.get(10, TimeUnit.SECONDS); // 10秒超时}).get(); }
📌 今日知识地图
模块 | 核心考点 |
---|---|
Java基础 | 模式匹配性能 |
MySQL | 索引下推+在线DDL避坑 |
Redis/Kafka | 跨中心ID生成+位移归档 |
JVM | CMS调优+堆外内存泄漏诊断 |
并发 | ForkJoin调优+StampedLock应用 |
Spring Cloud | 网关限流+安全审计+配置回滚 |
大模型 | 输出解析+向量分层+安全沙箱 |