AI+Java中级开发面试题库
生成时间:2026-05-20 23:47
【面试题】1. RAG系统中检索召回率低,常见的优化手段有哪些?请结合实际项目经验说明。
【标准答案】召回率低一般从三个维度优化。第一,Chunk策略优化——不要无脑按固定长度切分,要按语义边界切(比如按段落、按标题层级),chunk大小建议300-500 token,overlap 10%-20%,这样跨chunk的语义不会断裂。第二,检索方式升级——单路向量检索容易漏,改成混合检索:向量检索管语义相似,BM25关键词检索管精确匹配,用RRF或加权融合合并结果,召回率能提升15%-30%。第三,Query改写与扩展——用户原始query往往太短或表达模糊,用LLM做Query Expansion,生成2-3个同义改写一起检索,或者用HyDE让LLM先生成假设性答案再用答案做检索。实际项目中这三招组合用,基本能把召回率从60%拉到85%以上。
【面试题】2. Java中ConcurrentHashMap在JDK 1.8相比1.7做了哪些核心改进?为什么这么改?
【标准答案】核心改进两个。第一,锁粒度从Segment段锁改成了Node节点级别的CAS+synchronized——1.7用Segment分段锁,每个Segment是一把ReentrantLock,默认16段意味着最多16个并发写线程;1.8直接锁链表/红黑树的头节点,并发度等于桶数量,理论上无限并发。第二,数据结构从纯链表改成链表+红黑树——当链表长度超过8且数组长度>=64时转红黑树,查找从O(n)降到O(logn),hash冲突严重时性能差距巨大。为什么这么改?Segment设计太重了,Segment本身继承ReentrantLock,初始化就占大量内存,而且分段数固定不能动态扩展。改成节点级锁后内存省、并发度高、实现更简洁。面试时关键是要说清"锁粒度细化"这个核心思路。
【面试题】3. Spring AI中如何实现对大模型的Function Calling?请描述调用流程和关键代码结构。
【标准答案】Spring AI的Function Calling流程四步走。第一步,定义一个实现java.util.function.Function接口的类,泛型是<I, O>输入输出类型,用@Description注解描述函数功能,Spring AI会自动注册。第二步,在ChatClient调用时通过.functions("funcName")声明可用函数。第三步,运行时——用户提问后,模型判断需要调函数,返回一个tool_call请求;Spring AI框架自动拦截,根据函数名找到对应Bean,反序列化参数,执行函数,把结果拼回prompt再发给模型。第四步,模型拿到函数返回值后生成最终回答。关键点:函数注册是自动的,只要Bean在Spring容器中且标记了@Description;参数序列化/反序列化框架全包了;整个调用链是自动多轮的,模型可以连续调用多个函数。实际项目中注意控制函数数量,超过10个模型容易选错。
【面试题】4. MySQL中InnoDB的间隙锁(Gap Lock)是什么?在什么场景下会产生死锁?如何避免?
【标准答案】间隙锁是InnoDB在RR隔离级别下为了防止幻读而加的锁,锁住索引记录之间的"间隙",不让别的事务在这个范围插入新记录。比如事务A执行SELECT * FROM t WHERE id > 5 FOR UPDATE,不仅锁住id>5的已有记录,还锁住5到正无穷的间隙,事务B插入id=6就会被阻塞。死锁场景:事务A按id升序锁范围(5,10),事务B按id降序锁范围(8,3),A等B释放间隙,B等A释放间隙,死锁。避免方法:第一,按固定顺序加锁,所有事务都升序或都降序;第二,缩小查询范围,用等值查询代替范围查询减少间隙锁覆盖面;第三,降低隔离级别到RC(RC下没有间隙锁);第四,加锁时用SELECT ... FOR UPDATE配合合理索引,避免锁全表。面试官最爱听"固定顺序加锁"这个答案。
【面试题】5. 向量数据库(如Milvus/Pinecone)的HNSW索引原理是什么?为什么它比暴力搜索快?
【标准答案】HNSW全称Hierarchical Navigable Small World,核心思想是构建一个多层图结构,上层稀疏下层稠密。搜索时从最上层开始,每层找离目标最近的节点,然后往下跳到下一层继续找,类似跳表的思路。这样从顶层到底层逐步缩小范围,不用遍历所有向量。为什么比暴力搜索快?暴力搜索是O(n)逐一计算距离,HNSW利用图的小世界性质——任何两个节点之间只需少量跳转就能到达,搜索复杂度近似O(logn)。建图时每层通过贪心策略连接最近邻,保证了导航效率。实际使用中注意三个参数:M(每层最大连接数,越大精度越高但内存越大,推荐16-64)、efConstruction(建图时的搜索宽度,影响索引质量)、ef(查询时的搜索宽度,越大越准但越慢,生产环境建议ef=128-256)。面试时说出"多层图+跳表式导航"这个核心机制就够了。
【面试题】6. Java线程池的核心参数有哪些?拒绝策略怎么选?实际项目中如何动态调参?
【标准答案】七个核心参数:corePoolSize核心线程数、maximumPoolSize最大线程数、keepAliveTime空闲存活时间、unit时间单位、workQueue任务队列、threadFactory线程工厂、handler拒绝策略。拒绝策略四种:AbortPolicy抛异常(默认)、CallerRunsPolicy由提交线程执行(最常用,起到削峰作用)、DiscardPolicy静默丢弃、DiscardOldestPolicy丢弃队列最老任务。实际选型:大多数业务用CallerRunsPolicy,既不丢任务又能自然限流。动态调参:ThreadPoolExecutor提供了setCorePoolSize()和setMaximumPoolSize()方法,可以在运行时调整,不需要重启。实际项目中我们把线程池参数放在Nacos配置中心,写一个@RefreshScope的配置监听器,参数变更时调用set方法热更新。另外建议用自定义线程工厂给线程起有意义的名字,出了问题线程dump一目了然。
【面试题】7. AI Agent中ReAct模式的工作原理是什么?和纯Chain-of-Thought相比有什么优势?
【标准答案】ReAct是Reasoning + Acting的循环模式,每轮三步:Thought(推理当前该做什么)→ Action(调用工具执行)→ Observation(观察工具返回结果),然后进入下一轮循环,直到得出最终答案。和纯CoT的区别是:CoT只在脑子里想,ReAct是边想边动手。优势很直观——第一,能获取实时信息,纯CoT只能用训练时的知识,ReAct可以调搜索API、查数据库、读文件;第二,能验证推理结果,想错了可以看Observation修正,CoT想错了就一路错下去;第三,可解释性强,整个思考-行动-观察链路全程可追溯。实际开发中用LangChain的AgentExecutor或Spring AI的ChatClient就能实现ReAct模式,关键是定义好Tool描述,让模型知道什么时候该调什么工具。注意控制最大迭代次数,防止死循环。
【面试题】8. Redis分布式锁用SETNX实现有什么问题?Redlock算法解决了什么?生产环境怎么选?
【标准答案】基础SETNX锁三个问题:第一,不可重入——同一线程拿两次锁第二次会阻塞;第二,锁过期释放问题——业务没执行完锁就过期了,别的线程拿到锁导致并发冲突;第三,主从切换丢锁——主节点加锁后未同步到从就宕机,从升主后锁丢失。Redlock算法解决第三个问题:向N个独立Redis实例加锁,超过半数(N/2+1)加锁成功且总耗时小于锁有效期才算成功,这样单节点故障不影响锁安全。但Redlock争议很大,Martin Kleppmann写过文章批评它时钟依赖等问题。生产环境怎么选?如果只是防并发、允许极小概率出问题,用Redisson的RLock就行,它支持看门狗自动续期、可重入,够用了;如果对正确性要求极高(金融场景),直接上ZooKeeper或etcd的分布式锁,基于一致性协议不依赖时钟。面试时说清"看门狗续期"和"主从切换丢锁"这两个点就到位了。
【面试题】9. 大模型微调中LoRA的原理是什么?为什么它比全量微调更实用?
【标准答案】LoRA全称Low-Rank Adaptation,核心假设是预训练模型的权重矩阵在微调时的变化量是低秩的,不需要改整个矩阵,只需要学习一个低秩分解就行。具体做法:冻结原始权重W,新增两个小矩阵A和B,W' = W + BA,其中A是d×r的矩阵,B是r×d的矩阵,r就是秩,通常取8-64,远小于原始维度。为什么更实用?第一,参数量暴降——原始7B模型全量微调要训练7B参数,LoRA只训练0.1%-1%的参数;第二,训练速度快、显存占用低,单卡就能微调;第三,LoRA权重可以即插即用,基础模型共享,不同任务加载不同LoRA adapter就行,推理时合并到原始权重零额外延迟。实际项目中用PEFT库几行代码就能做LoRA微调,关键是选好r值和target_modules(通常选q_proj和v_proj)。面试官追问QLoRA的话,核心是4-bit量化+LoRA,显存再降一个量级。
【面试题】10. Spring Cloud中服务熔断和限流有什么区别?Sentinel和Resilience4j怎么选?
【标准答案】熔断是保护调用方——当下游服务异常率超过阈值,熔断器打开,后续请求直接走降级逻辑不再调用下游,给下游恢复时间,类似电路保险丝。限流是保护被调用方——控制单位时间内的请求量,超出部分排队或拒绝,防止流量压垮服务。两者保护对象不同,熔断保自己,限流保别人。Sentinel vs Resilience4j:Sentinel是阿里开源,功能全面(熔断+限流+热点+系统保护+集群流控),有可视化Dashboard实时监控,中文文档友好,但重、依赖多;Resilience4j是轻量级函数式设计,只有熔断、限流、重试、隔离仓四个核心模块,零依赖,适合云原生轻量架构。选型建议:项目已经用Spring Cloud Alibaba生态就选Sentinel无缝集成;追求轻量、已经在用Spring Cloud 2020+版本就选Resilience4j。面试官喜欢听"熔断保调用方、限流保服务方"这个区分。