本轮 AI+Java中级开发面试题库(带答案)
生成时间:2026-05-20 22:37
【面试题】1. RAG系统中检索到的文档片段相关性不高,导致大模型回答"跑偏",你会怎么优化?
【标准答案】我会从三个层面入手。检索层面:先看chunk切分策略是否合理——太大会混入无关内容,太小会丢失上下文,一般512-1024 token比较合适;然后引入混合检索,把BM25关键词召回和向量语义召回做加权融合,互相补短板;最后对top-k结果做rerank重排序,用cross-encoder精排把真正相关的片段提上来。提示词层面:在system prompt里明确告诉模型"只根据以下参考资料回答,不确定的就说不知道",减少幻觉。工程层面:加元数据过滤,比如按文档类型、时间范围先过滤一轮再检索,缩小检索空间。实际项目中这三招组合使用,准确率提升非常明显。
【面试题】2. Java中HashMap和ConcurrentHashMap的区别是什么?ConcurrentHashMap在JDK1.8做了哪些改进?
【标准答案】HashMap线程不安全,多线程put可能导致死循环(1.7头插法链表成环)或数据丢失。ConcurrentHashMap是线程安全的。1.7 vs 1.8的核心区别:1.7用Segment分段锁,每个Segment继承ReentrantLock,默认16段,并发度固定;1.8取消了Segment,改用CAS+synchronized,锁粒度从段级降到桶级别(每个Node头节点加锁),并发度等于桶数量,大幅提升。1.8的另一个改进:链表长度超过8且数组长度≥64时转红黑树,查找从O(n)降到O(logn)。面试关键点:1.8的synchronized锁的是桶头节点,不是整个表,所以不同桶可以并发操作,这是性能提升的核心。
【面试题】3. 什么是AI Agent?和普通的Prompt调用有什么本质区别?
【标准答案】普通Prompt调用是一次性的:输入prompt→输出结果,没有自主性。AI Agent的核心区别是自主决策循环——它能在运行中自己决定下一步做什么。具体来说,Agent具备四个要素:感知(接收环境和用户输入)、推理(用LLM做规划和决策)、行动(调用工具/API/数据库等)、记忆(短期对话上下文+长期知识存储)。比如用户说"帮我查下北京天气并订机票",普通prompt做不到,但Agent可以:先调天气API获取信息,再调订票API完成操作,中间根据返回结果决定下一步。技术框架层面,LangChain的Agent+Tools机制、Spring AI的Function Calling都是实现这个模式。
【面试题】4. JVM内存模型中,新生代和老年代的GC策略分别是什么?什么情况下对象会直接进入老年代?
【标准答案】新生代用复制算法(Eden + Survivor0 + Survivor1,默认8:1:1),Minor GC时存活对象复制到另一个Survivor,年龄+1。老年代用标记-整理或标记-清除,Full GC触发。对象直接进老年代的几种情况:①大对象(超过-XX:PretenureSizeThreshold阈值)直接分配到老年代,避免在新生代大量复制;②长期存活对象(年龄达到15,-XX:MaxTenuringThreshold)晋升;③Survivor区相同年龄对象大小总和超过Survivor空间一半,该年龄及以上的直接晋升(动态年龄判断);④Minor GC后Survivor放不下,通过担保机制进入老年代。面试加分点:说清楚为什么要有这些机制——核心是为了减少Full GC频率。
【面试题】5. Spring AI中Function Calling的工作原理是什么?如何让大模型调用本地Java方法?
【标准答案】Spring AI的Function Calling流程:第一步,用@Description注解或Bean定义注册一个Java函数,描述它的功能;第二步,ChatClient发起请求时把函数描述传给大模型;第三步,大模型判断是否需要调用函数,如果需要,返回一个function_call响应(包含函数名和参数JSON);第四步,Spring AI自动拦截这个响应,反射调用对应的Java方法,拿到返回值;第五步,把返回值作为工具结果拼回prompt,再次请求大模型生成最终回答。整个过程对开发者是透明的——你只需要写Java方法+注册,框架帮你处理调度。关键配置是ChatOptions里指定要暴露哪些functions,以及temperature设低一点让模型更倾向调工具。
【面试题】6. Redis分布式锁用SETNX实现有什么问题?Redlock算法能解决吗?
【标准答案】SETNX的问题:①锁过期但业务没执行完,被其他线程获取,导致并发冲突——解法是看门狗机制自动续期;②客户端宕机锁无法释放——解法是加过期时间,但SETNX和EXPIRE非原子——解法是用SET key value NX EX seconds原子命令;③主从同步延迟,主节点加锁后宕机,从节点没同步到锁信息,另一个客户端又加锁成功——这是最核心的问题。Redlock:在多个独立Redis实例(通常5个)上同时加锁,超过半数(3个)成功才算获取锁,解决了单点故障问题。但Redlock有争议——Martin Kleppmann指出它依赖时钟同步,在网络分区等场景下不安全。实战建议:大多数场景用Redisson的RLock(看门狗续期+可重入)就够了;对一致性要求极高的用ZooKeeper或etcd。
【面试题】7. 向量数据库(如Milvus/Qdrant)的索引类型有哪些?如何选择?
【标准答案】核心索引类型分几类:FLAT——暴力搜索,精度最高但速度最慢,适合小数据量(<10万);IVF(倒排索引)——先用K-means聚类,搜索时只查最近的nprobe个簇,速度和精度的折中方案,适合百万级;HNSW(层级可导航小世界图)——基于图的近似最近邻,查询速度极快,召回率高,是当前最流行的索引,适合实时性要求高的场景;PQ(乘积量化)——把向量压缩编码,内存占用极低,适合亿级数据但精度有损失。选择原则:小规模用FLAT保精度;百万级+实时查询用HNSW;亿级+内存有限用IVF+PQ组合;对召回率要求不高但要求极快用IVF。面试关键点:所有向量索引都是近似搜索(ANN),不是精确搜索,这是精度和速度的trade-off。
【面试题】8. MySQL中InnoDB的MVCC机制是怎么实现的?它能解决幻读吗?
【标准答案】MVCC通过隐藏列+Undo Log+ReadView实现。每行数据有两个隐藏列:trx_id(最后修改的事务ID)和roll_pointer(指向Undo Log中的前版本链)。ReadView是事务开始时创建的快照,记录当前活跃事务ID列表,通过比较trx_id判断版本是否可见:trx_id小于ReadView中最小活跃ID→可见;大于最大ID→不可见;在中间看是否在活跃列表中→在则不可见。RR级别:ReadView在事务第一次SELECT时创建并复用,所以同一事务多次读结果一致。RC级别:每次SELECT都创建新的ReadView。能否解决幻读:快照读(普通SELECT)通过MVCC解决了幻读;但当前读(SELECT FOR UPDATE/INSERT/UPDATE)会读最新数据,MVCC管不了,这时靠Gap Lock+Next-Key Lock来防止幻读。所以严格说,InnoDB在RR级别通过MVCC+间隙锁组合才解决了幻读。
【面试题】9. 大模型微调方式LoRA的原理是什么?和全量微调相比有什么优劣?
【标准答案】LoRA(Low-Rank Adaptation)的核心思想:大模型参数矩阵W是d×d的,全量微调要更新所有参数;LoRA冻结原始权重W,旁边加一个低秩分解 W'=W + BA,其中B是d×r,A是r×d,r远小于d(比如r=8或16)。这样可训练参数从d²降到2×d×r,减少几个数量级。优势:①训练参数极少,显存占用大幅降低,单卡能微调大模型;②训练好的LoRA权重很小(几MB到几十MB),可以像插件一样切换,多个任务共享基座模型;③推理时可以合并到原始权重,零额外延迟。劣势:①表达能力上限低于全量微调,复杂任务可能不够;②rank选择需要实验,太小欠拟合太大过拟合;③多个LoRA同时服务时需要动态加载。实战建议:大多数业务场景LoRA够用,先试LoRA,效果不行再考虑全量微调。
【面试题】10. Kafka如何保证消息不丢失?生产者、Broker、消费者三个环节分别怎么做?
【标准答案】三个环节都要处理:生产者端:acks参数设为all(或-1),确保所有ISR副本都确认写入才返回成功;同时开启重试retries,配合幂等性参数enable.idempotence=true防止重试导致重复。Broker端:min.insync.replicas设为≥2,配合acks=all确保至少2个副本写入成功;unclean.leader.election.enable设为false,禁止非ISR副本成为Leader,防止数据丢失;副本因子replication.factor≥3。消费者端:关闭自动提交enable.auto.commit=false,业务处理完成后再手动提交offset;如果是消费+写入数据库的场景,用事务或幂等表保证Exactly-Once语义。面试关键点:三层防御缺一不可,只做一层都不保险。另外要提一下,Kafka的Exactly-Once是靠事务+幂等实现的,不是靠单独某个配置。