本轮 AI+Java中级开发面试题库(带答案)
【面试题】1. 大模型推理时KV Cache的作用是什么?如果没有它,自回归生成会有什么问题?
【标准答案】KV Cache是大模型推理加速的核心机制。自回归生成时,每生成一个token都要对前面所有token做Attention,如果没有KV Cache,每一步都要重新计算前面所有token的Key和Value矩阵,复杂度是O(n²)。有了KV Cache,把已算过的Key、Value缓存下来,每步只算新token的Q去和缓存的KV做Attention,复杂度降到O(n)。实际推理中KV Cache能带来3-5倍的加速,是推理服务能否上线的生命线。但它的代价是显存占用随序列长度线性增长,所以长上下文场景下要做KV Cache量化或PagedAttention等优化。
【面试题】2. 提示词工程中,Chain-of-Thought和Tree-of-Thought有什么区别?分别适合什么场景?
【标准答案】CoT是让模型"一步一步想",把推理链路线性展开,适合数学计算、逻辑推理这类有明确递进路径的问题。ToT是把推理过程组织成树状结构,每一步生成多个候选分支,然后评估筛选,选最优路径继续往下走,适合需要回溯和探索的场景,比如创意规划、多步决策、游戏策略。打个比方:CoT是走迷宫只往一条路走到底,ToT是在岔路口都试试再选最好的那条。实际项目中,CoT用得多因为成本低、效果好;ToT效果好但token消耗大,一般在关键决策节点才用。
【面试题】3. RAG系统中向量检索的Top-K结果不理想,你会从哪些方面优化?
【标准答案】我会分四层排查优化。第一层,Embedding模型——换更强的模型或针对领域微调,通用模型在专业领域语义对齐差。第二层,Chunk策略——调整切分粒度和重叠度,太长会稀释关键信息,太短丢失上下文,加语义切分比固定长度效果好。第三层,检索策略——混合检索(向量+关键词BM25)比纯向量检索更稳,加Rerank重排序把真正相关的推到前面。第四层,Query优化——做Query改写或HyDE(让模型先假设一个答案再检索),把模糊问题变成精确检索词。实际经验看,Rerank和混合检索是性价比最高的两步优化。
【面试题】4. Spring AI中如何实现一个多轮对话的ChatClient?和直接调用大模型API有什么本质区别?
【标准答案】Spring AI的ChatClient封装了对话历史管理、Prompt模板、输出解析等能力。核心是ChatMemory机制,自动维护会话上下文窗口——你不用手动拼接history,ChatClient每次调用自动把历史消息塞进请求。直接调API的话,你得自己管理消息列表、手动截断超长上下文、处理流式响应的拼接。Spring AI还支持Advisor拦截器模式,可以在请求前后插入日志、限流、内容审核等逻辑,类似Spring MVC的Filter。本质区别:调API是"裸调",Spring AI是"工程化封装",生产环境必须用后者,否则对话管理、异常处理、可观测性全是坑。
【面试题】5. AI Agent的ReAct框架中,"思考-行动-观察"循环的终止条件怎么设计?如何避免死循环?
【标准答案】终止条件设计三种。第一,最大步数限制——设硬上限比如10步,到数强制停止并输出已有结论,这是兜底。第二,目标达成检测——在Prompt中明确告诉Agent"当你能回答用户问题时直接输出Final Answer",通过输出格式约束来判断,比如检测到"Final Answer:"字段就终止。第三,观察无变化检测——连续两步Observation相同或相似度超过阈值,说明陷入循环,强制退出。避免死循环的关键:每步Action必须产生新信息或改变状态,禁止重复调用同一Tool且参数相同。实际项目中,最大步数兜底是必须的,因为LLM的输出不可控。
【面试题】6. Java线程池的核心参数有哪些?如何根据业务场景合理设置?
【标准答案】ThreadPoolExecutor七个核心参数:corePoolSize(核心线程数)、maximumPoolSize(最大线程数)、keepAliveTime(非核心线程空闲存活时间)、unit(时间单位)、workQueue(任务队列)、threadFactory(线程工厂)、handler(拒绝策略)。设置原则:CPU密集型任务,核心线程数设为CPU核数+1;IO密集型任务,设为CPU核数×2或用公式 N×(1+WT/ST),WT是等待时间ST是计算时间。任务队列选型:有界队列防OOM,LinkedBlockingQueue默认无界很危险。拒绝策略:生产环境不建议用默认AbortPolicy,一般用CallerRunsPolicy让调用线程自己跑,起到削峰作用。关键是监控——上线后必须观察队列积压和线程利用率再调。
【面试题】7. Spring Boot自动装配的原理是什么?如何自定义一个Starter?
【标准答案】核心是@EnableAutoConfiguration注解,它通过SpringFactoriesLoader扫描所有jar包META-INF/spring.factories(Spring Boot 3.x改为META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports),加载AutoConfiguration类。每个AutoConfiguration类用@Conditional系列注解做条件判断,满足才装配。自定义Starter三步:第一步,写自动配置类,用@ConditionalOnClass、@ConditionalOnMissingBean等条件注解;第二步,在META-INF/spring.factories里注册配置类;第三步,提供默认配置属性类用@ConfigurationProperties。命名规范:官方spring-boot-starter-xxx,第三方xxx-spring-boot-starter。关键是@ConditionalOnMissingBean,让用户可以覆盖默认Bean。
【面试题】8. MySQL中索引失效的常见场景有哪些?如何用EXPLAIN分析?
【标准答案】常见失效场景:1)对索引列使用函数或运算,如WHERE YEAR(create_time)=2024;2)隐式类型转换,varchar列用数字查;3)LIKE以通配符开头,LIKE '%abc';4)OR条件中有一列无索引;5)联合索引不满足最左前缀原则;6)查询条件用NOT IN、!=、IS NOT NULL;7)优化器判断全表扫描更快(数据量小时常见)。用EXPLAIN分析:重点看type列(const>eq_ref>ref>range>index>ALL,ALL就是全表扫描),key列看用了哪个索引,rows列看预估扫描行数,Extra列看是否有Using filesort或Using temporary(出现就是危险信号)。实际优化时,加索引前先EXPLAIN确认确实走不上索引,加完再EXPLAIN验证。
【面试题】9. Redis分布式锁用SETNX实现有什么问题?RedLock算法解决了什么,又引入了什么新问题?
【标准答案】基础SETNX+EXPIRE有两个经典问题:1)非原子性——SETNX成功但EXPIRE没执行,死锁。解决:用SET key value EX NX原子命令。2)误删——客户端A锁过期自动释放,客户端B加锁成功,A回来执行DEL把B的锁删了。解决:value用唯一标识,删锁时Lua脚本先比较再删。RedLock在多个独立Redis实例上同时加锁,过半成功才算获取锁,解决了单节点故障问题。但RedLock引入新问题:1)时钟漂移——不同节点时钟不同步可能导致锁提前释放;2)网络分区下仍可能两个客户端同时持有锁;3)性能开销大,要和5个节点通信。Martin Kleppmann专门写文批评RedLock,建议用单实例+可靠租约,或直接用ZooKeeper/etcd。
【面试题】10. 微服务下分布式事务的Saga模式怎么实现?和2PC相比各自的适用场景?
【标准答案】Saga把长事务拆成多个本地事务,每个本地事务完成后发事件触发下一个,如果某步失败就执行补偿事务回滚。两种实现:编排式(Choreography)——纯事件驱动,服务间无中心协调,松耦合但流程不直观,调式难;编排式(Orchestration)——有中心协调器控制流程,逻辑清晰但协调器是单点。和2PC对比:2PC强一致性,锁资源时间长,适合短事务、一致性要求高的场景如金融转账;Saga最终一致性,无锁等待,适合长事务如订单流程(下单→扣库存→支付→发货)。实际选型:电商订单用Saga,银行转账用2PC或TCC。Spring Cloud里Seata支持Saga和TCC两种模式,看业务选。