AI+Java中级开发面试题库(2026-05-24 21:48)
【面试题】1. RAG检索增强生成的核心原理是什么?在生产环境如何优化检索质量?
【标准答案】RAG的核心是把检索和生成解耦,先从知识库召回相关文档,再喂给大模型生成答案。关键点有三个:一是召回质量决定上限,二是上下文窗口管理,三是检索和生成的平衡。
生产环境优化我有三步走策略:第一,检索端用混合检索,关键词BM25抓精确匹配,向量检索抓语义相关,然后做RRF融合排序;第二,切片策略要因地制宜,大文档按段落切,表格保持结构完整,代码按函数粒度切;第三,加重排序层,用Cross-Encoder模型对召回的Top-K做精排,一般能提升20%以上的准确率。
我之前的项目中,我们还做了元数据过滤,比如按文档类型、时间范围、部门标签做预过滤,先把检索范围从百万级降到万级,再上向量召回,性能和精度都提上来了。
【面试题】2. Java线程池的7个核心参数,在生产环境怎么配置?拒绝策略怎么选?
【标准答案】7个参数是:corePoolSize核心线程数、maximumPoolSize最大线程数、keepAliveTime空闲线程存活时间、unit时间单位、workQueue工作队列、threadFactory线程工厂、handler拒绝策略。
生产环境配置我有三个原则:一是核心线程数看CPU密集还是IO密集,CPU密集型设置为CPU核数+1,IO密集型可以翻倍甚至更多;二是队列长度要有上限,别用无界队列,否则线程池满了也不报错,OOM了才发现;三是拒绝策略优先选CallerRunsPolicy,让提交任务的线程自己去执行,既不丢任务又能产生背压,下游服务不会被压垮。
我们线上还有一个做法:动态线程池。把核心参数放到配置中心,根据监控指标动态调整,比如请求量上来就扩容,夜间低谷就缩容,既省钱又稳定。
【面试题】3. 向量数据库选型要考虑哪些因素?Milvus和Pinecone怎么选?
【标准答案】选型看五个维度:规模、性能、生态、成本、运维复杂度。
规模上,百万级向量用单机够了,千万到亿级就要分布式集群;性能上,看QPS和延迟要求,实时检索要求P99在百毫秒内;生态上,看有没有现成的SDK,LangChain、Spring AI有没有集成;成本上,自建用开源免费但要人力,SaaS按量计费但省心;运维上,自建要搞定扩缩容、备份恢复、监控告警。
Milvus是开源的,适合对数据安全要求高、有运维团队的场景,我们自建就是用的Milvus,上了Kubernetes,做了分布式部署,十亿级向量检索P99在50毫秒以内。Pinecone是全托管SaaS,开箱即用,适合快速验证或小团队,但数据要上云,合规性要求高的场景要慎重。
我的建议是:初创团队或POC阶段用Pinecone快速上线,验证OK再考虑自建Milvus降成本。
【面试题】4. JVM垃圾回收器的选择策略?G1和ZGC在什么场景下用?
【标准答案】JDK 8默认Parallel GC,适合吞吐量优先的批处理场景;JDK 9之后G1是默认,适合响应敏感的在线服务;JDK 11开始ZGC可用,JDK 15正式可用,主打低延迟大堆内存。
G1的思路是把堆分成多个Region,优先回收垃圾最多的Region,用停顿预测模型控制每次GC时间。适合4-8GB堆内存、停顿目标在200ms以内的场景。我们微服务就是用的G1,配合-XX:MaxGCPauseMillis=200,线上P99延迟稳定在100ms左右。
ZGC是并发整理的,大部分工作都在应用线程运行时做,停顿时间不随堆大小增长。适合超大堆内存,比如几十GB甚至TB级,或者对延迟极度敏感的场景。但ZGC吞吐量会略低,大概损失15%左右,而且启动时内存占用大。
我的经验是:堆内存小于8GB用G1够用,超过16GB或者停顿要求在10ms以内,上ZGC。
【面试题】5. Spring AI框架如何实现一个带记忆的对话助手?
【标准答案】Spring AI提供了ChatMemory接口来管理对话历史。核心思路是:每次对话把用户问题和AI回复存到memory,下次对话时先从memory捞历史上下文,拼到prompt里,再调用大模型。
实现分三步:第一步,配置ChatMemory,可以用InMemoryChatMemory做测试,生产用Redis或数据库持久化;第二步,在ChatClient里注入ChatMemoryAdvisor,设置对话窗口大小,比如保留最近10轮;第三步,调用时传入conversationId,框架会自动按会话ID隔离历史。
ChatClient client = ChatClient.builder(chatModel)
.defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory))
.build();
String response = client.prompt()
.user(question)
.advisors(advisor -> advisor.param("conversationId", sessionId))
.call()
.content();我们项目还做了Token预算控制,设置maxTokens上限,历史消息超过限制就按重要性裁剪,保留关键信息又不爆上下文。
【面试题】6. Redis分布式锁用SETNX实现有什么问题?Redisson是怎么解决的?
【标准答案】原生SETNX有三个坑:一是锁没有过期时间,客户端宕机锁就死锁了;二是误删别人的锁,客户端A的锁过期了,但A还在执行,B拿到锁,A执行完把B的锁删了;三是单点故障,Redis挂了锁就不可用了。
Redisson解决得很优雅:第一,用Lua脚本原子地SET锁并设置过期时间,解决死锁;第二,用watchdog看门狗自动续期,业务没执行完锁不会过期;第三,加锁时生成唯一ID,解锁时校验是自己的锁才删,用Lua保证原子性;第四,支持RedLock算法,多节点同时加锁,超过半数成功才算拿到锁,解决单点问题。
RLock lock = redisson.getLock("myLock");
lock.lock(30, TimeUnit.SECONDS);
try {
// 业务逻辑
} finally {
lock.unlock();
}我们线上还配置了waitTime,设置最多等待5秒拿锁,拿不到就降级处理,避免大量请求阻塞。
【面试题】7. AI Agent的规划能力怎么实现?ReAct框架的核心思想是什么?
【标准答案】AI Agent的核心是让大模型能自主规划和执行任务。ReAct框架把推理和行动结合起来,形成"思考-行动-观察"的循环:先Thought思考下一步该做什么,再Action调用工具,然后Observation观察结果,再进入下一轮思考,直到任务完成。
实现上分三步:第一,定义工具集,每个工具描述清楚能力、入参、返回,让模型知道什么时候用什么工具;第二,用Few-Shot示例教模型怎么拆解任务,比如"查天气→定行程→订机票";第三,设计停止条件,比如"Final Answer"表示任务完成,或者达到最大步数上限。
prompt = """
你是一个助手。可用工具:search(query), calc(expression)
格式:
Thought: 我需要...
Action: search
Action Input: 北京天气
Observation: 晴,25度
Thought: 天气不错...
Final Answer: 建议出行
"""我们做订单助手时,用了ReAct+工具编排,Agent会自动判断:查库存→算价格→调用支付→通知仓库,多步骤串联,用户只需要一句话。
【面试题】8. MySQL索引优化,什么情况下索引会失效?
【标准答案】索引失效有六种典型场景:
第一,最左前缀不满足,联合索引(a,b,c),查询条件只有b或c,索引用不上;
第二,在索引列上做运算,比如WHERE YEAR(create_time) = 2024,函数会把索引干掉,要改成范围查询;
第三,隐式类型转换,比如phone字段是varchar,查询用WHERE phone = 13800138000,数字和字符串比较,MySQL会做转换,索引失效;
第四,LIKE左模糊,WHERE name LIKE '%张',前面是通配符,B+树有序性用不上;
第五,OR条件有一列没索引,WHERE a = 1 OR b = 2,如果b没索引,整个条件都不会走索引;
第六,NOT IN、NOT EXISTS、<>操作,在数据量大的情况下优化器可能直接全表扫描。
我们线上还遇到过索引选择性差的问题,比如性别字段只有男女两种值,建了索引优化器也不用,因为回表成本比全表扫描还高。这种场景要么不建索引,要么结合其他字段建联合索引。
【面试题】9. 大模型Prompt Engineering,如何设计一个稳定可靠的提示词模板?
【标准答案】提示词设计我有四个原则:角色定义清晰、任务描述具体、约束条件明确、输出格式标准化。
一个稳定的模板结构是:角色设定→任务说明→输入数据→约束条件→输出格式→Few-Shot示例。
你是一个Java代码审查专家,专注于发现代码缺陷和性能问题。
任务:审查以下代码,识别潜在的Bug、性能隐患和设计问题。
代码:
{code}
约束条件:
1. 只关注实质性改进,不提代码风格问题
2. 按严重程度排序:高危>中等>建议
3. 每个问题必须给出修复建议
输出格式(JSON):
{
"issues": [
{"severity": "高", "line": 10, "problem": "...", "fix": "..."}
]
}
示例:
输入:List list = new ArrayList();
输出:{"issues":[{"severity":"中","line":1,"problem":"未指定容量","fix":"new ArrayList<>(100)"}]}我们还做了提示词版本管理,每次调优记录效果指标,A/B测试稳定了再上线。关键是Few-Shot示例要覆盖边界case,不然模型会胡编。
【面试题】10. 分布式事务Seata的AT模式原理是什么?有什么局限性?
【标准答案】Seata的AT模式是二阶段提交的优化版。核心思路是:第一阶段记录前后镜像快照,提交本地事务并释放锁;第二阶段全局提交就直接删快照,回滚就用快照做反向SQL还原数据。
原理拆解:一阶段执行业务SQL时,Seata会拦截SQL,解析语义,生成前后镜像存到undo_log表,然后提交本地事务,效率很高;二阶段如果全局提交,异步删除undo_log,如果全局回滚,从undo_log读快照,生成反向SQL回滚数据。
局限性有四点:第一,脏写问题,如果有一个分支事务在全局提交前被其他事务改了,回滚时会用脏数据覆盖,要用全局锁解决;第二,性能依赖undo_log,高频写入场景undo_log表会成为瓶颈;第三,SQL支持有限,复杂SQL可能解析失败;第四,全局锁粒度是行锁,热点数据会有竞争。
我们项目对一致性要求不高的场景用AT,比如订单状态更新,失败了可以补偿;核心资金交易用TCC,自己实现幂等和回滚逻辑,更可控。
生成时间:2026-05-24 21:48
题目数量:10道(AI方向5道 + Java方向5道)
覆盖类型:技术基础、架构设计、场景实操、性能优化、框架应用