本轮 AI+Java中级开发面试题库(带答案)
【面试题】1. RAG系统中,向量检索召回的chunk往往存在语义截断问题,你怎么解决?
【标准答案】语义截断是RAG的老大难问题,chunk边界刚好切断关键信息。我的做法是三层防护:第一,分块策略上用语义分块代替固定长度分块,按段落或句子边界切,同时做重叠切分(overlap 10%-20%),保证跨chunk信息不丢;第二,检索阶段做多路召回,向量检索+关键词BM25双路,再加分段元数据过滤,提升召回率;第三,后处理阶段对top-k结果做重排序,用cross-encoder精排,并且对相邻chunk做合并去重,避免同一语义段被切成多条重复返回。落地时还要注意chunk size要结合模型上下文窗口动态调整,不能一刀切。
【面试题】2. ConcurrentHashMap在JDK1.8之后为什么放弃Segment分段锁?现在的实现是怎样的?
【标准答案】JDK1.7的Segment分段锁问题是锁粒度固定为16段,并发度无法动态扩展,而且Segment本身是ReentrantLock,内存开销大。1.8改用CAS+synchronized,锁粒度降到单个桶的头节点,并发度随table长度动态增长。具体流程:put时先判断桶是否为空,空则CAS写入;非空则synchronized锁住头节点再操作。这样做的优势:第一,锁粒度更细,冲突更少;第二,synchronized在JDK1.6后有偏向锁、轻量级锁等优化,多数无竞争场景比ReentrantLock性能更好;第三,省掉了Segment数组的内存开销。扩容时采用多线程协同迁移,每个线程负责一段桶,通过transferIndex原子递减分配任务,效率比1.7高很多。
【面试题】3. Spring AI和LangChain相比,在Java技术栈中做AI应用各有什么优劣?
【标准答案】LangChain是Python生态的AI应用框架,生态最丰富、社区最活跃,链式调用和Agent编排很成熟,但Python本身在工程化上有短板——类型安全弱、性能差、部署需要独立运行时。Spring AI是Spring生态的AI整合方案,优势是和Spring Boot深度集成,依赖注入、配置管理、Actuator监控开箱即用,Java强类型让代码更可靠,适合企业级项目;劣势是起步晚,Agent编排能力不如LangChain灵活,模型和工具的生态覆盖面还差一截。我的选择:新项目如果团队以Java为主、已有Spring体系,用Spring AI上手快、维护成本低;如果需要快速验证复杂的Agent链路或用到最新模型能力,LangChain更快。实际中也可以混合——核心业务用Spring AI,AI编排层用LangChain通过HTTP gRPC对接。
【面试题】4. 说说MySQL的索引下推(ICP)是怎么回事?在什么场景下能提升性能?
【标准答案】索引下推是MySQL 5.6引入的优化,核心思想是把存储引擎层的索引过滤条件"下推"到索引扫描阶段执行,减少回表次数。举个例子:联合索引(a,b),查询select * from t where a > 10 and b = 5,没有ICP时,存储引擎按a>10扫出所有满足的记录,每条都回表取整行,再由Server层判断b=5;有ICP时,存储引擎在索引里就判断b=5,不满足的直接跳过,只对同时满足a>10和b=5的记录回表。适用条件:必须是联合索引、查询条件有索引列但无法全部用作索引前缀、索引列上有过滤条件。注意覆盖索引场景下ICP不生效,因为根本不需要回表。实际优化中,ICP的收益取决于能过滤掉多少行,过滤比例越高提升越大。
【面试题】5. 大模型推理时KV Cache的原理是什么?为什么它能加速推理但不增加显存就玩不转?
【标准答案】Transformer自回归推理时,每生成一个token都要对前面所有token做注意力计算,KV Cache就是把每层每头的Key和Value矩阵缓存下来,新token只需算Query和已有KV做注意力,避免重复计算前面的KV。加速原理:把每步O(n²)的KV计算变成O(n)的增量计算。但代价是显存占用随序列长度线性增长——每层每个KV head都要存,层数×头数×序列长度×维度×2字节(fp16),Llama2-70B跑4K上下文光KV Cache就要几十GB。所以长上下文场景下KV Cache是显存杀手。优化手段:第一,MQA/GQA减少KV头数;第二,PagedAttention像虚拟内存一样分页管理KV Cache,避免预分配浪费;第三,量化KV Cache到FP8/INT4;第四,Sliding Window Attention只缓存窗口内的KV。
【面试题】6. Redis分布式锁用SETNX实现有什么坑?Redlock算法能解决吗?
【标准答案】简单SETNX加锁有三个经典坑:第一,锁过期但业务没执行完,别的线程拿到锁导致并发冲突——需要看门狗续期(Redisson的做法);第二,锁的误删——A的锁过期释放了,B拿到了锁,A执行完把B的锁删了——需要value带唯一标识,解锁时Lua脚本校验再删保证原子性;第三,主从切换时锁丢失——主节点加锁成功但还没同步给从就挂了,从升为主后没有锁信息,第二个客户端又能加锁。Redlock算法试图解决第三个问题:向N个独立Redis实例加锁,超过半数成功才视为获取锁。但Redlock本身争议很大:分布式系统专家Martin Kleppmann指出它依赖时钟同步、在GC暂停和网络分区下不安全,推荐用fencing token方案。实际生产中,大多数场景用Redisson的看门狗+Lua解锁就够,对正确性要求极高的场景用ZooKeeper或etcd更靠谱。
【面试题】7. 设计一个AI Agent系统,让它能调用多个外部API完成复杂任务,你会怎么设计?
【标准答案】核心是Tool Use能力编排。架构上分四层:第一层是意图理解,LLM接收用户输入,判断需要调用哪些工具、以什么顺序;第二层是工具注册与发现,每个外部API封装为Tool描述(name + description + parameters JSON Schema),注册到Tool Registry供LLM选择;第三层是执行引擎,拿到LLM的tool_call决策后,参数校验→权限检查→调用API→处理结果→反馈给LLM继续推理,形成ReAct循环;第四层是记忆层,短期记忆放对话上下文,长期记忆用向量库存储历史工具调用结果和知识。关键设计点:工具描述要精确,LLM选错工具是最常见的失败原因;加重试和降级,外部API可能超时或报错;加安全沙箱,限制工具调用权限和频率;复杂任务用Plan-then-Execute,先让LLM规划步骤再逐步执行,避免ReAct循环死锁。框架选型上LangChain的Agent或Spring AI的Function Calling都能实现。
【面试题】8. JVM的G1收集器和ZGC分别适合什么场景?生产环境怎么选?
【标准答案】G1是分代收集器,把堆划分为等大Region,通过优先回收价值高的Region控制停顿时间,-XX:MaxGCPauseMillis设目标。适合6GB以上堆、停顿要求在200ms以内的一般业务。G1的Young GC是STW的,Mixed GC也有短暂停顿,调优重点是避免并发标记期间对象分配速度超过回收速度导致Full GC。ZGC是JDK15转正的超低延迟收集器,核心优势是STW时间亚毫秒级(通常<1ms),且和堆大小无关——因为读屏障+染色指针让对象迁移可以并发进行。适合超大堆(几十GB到TB级)且对延迟极度敏感的场景,如金融交易、实时推荐。但ZGC不分代(JDK21后才支持分代ZGC),吞吐量在高分配速率场景可能不如G1。选择建议:堆<16GB、延迟容忍100-200ms,G1够用且稳定;堆>16GB或延迟要求<10ms,选ZGC。JDK21+的分代ZGC是未来趋势,兼顾低延迟和吞吐。
【面试题】9. Spring Cloud微服务中,服务A调用服务B再调用服务C,如果C超时了,怎么防止A也被拖死?
【标准答案】核心是隔离和快速失败。第一层,超时控制要逐层收紧:A调B设3s超时,B调C设2s超时,不能让C的超时穿透到A。第二层,熔断器保护:B对C的调用加熔断(Sentinel或Resilience4j),当C超时率达到阈值,熔断器打开,B直接快速失败返回降级结果,不再调C,A也不会被阻塞等待。第三层,隔离策略:调用C的线程池或信号量隔离(如Sentinel的线程池隔离),C慢了只占用自己的线程池,不会耗尽B的所有线程。第四层,A自身也要有兜底:A调B也要设超时+熔断,即使B没做好隔离,A也不会被拖死。第五层,监控告警:全链路追踪(Sleuth+Zipkin)定位慢调用,及时发现问题。关键原则:每一层都要假设下游不可靠,做好自我保护,不能把"别人慢"变成"我也慢"。
【面试题】10. 提示词工程中的Chain-of-Thought和Tree-of-Thought有什么区别?分别适合什么任务?
【标准答案】CoT是让模型一步一步推理,把中间思考过程显式写出来再给答案,类似人做数学题写过程。适合线性推理任务——数学计算、逻辑推导、常识推理,特点是推理路径单一,中间步骤有因果递进关系。Few-shot CoT给几个带推理过程的示例效果最好,Zero-shot CoT就加一句"Let's think step by step"也能显著提升。ToT是CoT的升级版,允许模型在每一步生成多个候选思考分支,形成树状搜索空间,然后用评估器对每个分支打分,选择最有希望的路径继续探索,可以回溯。适合需要探索和试错的复杂任务——24点游戏、创意写作规划、多步策略决策。区别本质:CoT是贪心搜索,一条路走到底;ToT是树搜索(BFS/DFS),允许试错回溯。代价是ToT的token消耗远高于CoT,需要多次LLM调用。实际选择:简单推理用CoT性价比最高,复杂规划且允许额外计算成本的用ToT,中间态还有ReAct(推理+行动交替)作为折中方案。