Skip to content

AI+Java中级开发面试题库 ​

生成时间: 2026-05-23 16:15
题目数量: 10道(AI 5道 + Java 5道)


【面试题】1. Transformer模型中的Self-Attention机制是如何工作的?为什么它比RNN更适合处理长文本? ​

【标准答案】Self-Attention的核心是计算序列中每个词与其他所有词的关联权重。具体来说,输入经过三个线性变换得到Query、Key、Value三个矩阵,然后用Query和Key做点积得到注意力分数,经过Softmax归一化后与Value相乘,得到加权后的输出。

为什么比RNN更适合长文本?主要有三点:第一,并行计算,RNN必须串行处理,而Self-Attention可以同时计算所有位置,训练速度快很多;第二,长距离依赖,RNN处理长序列时信息会衰减,而Self-Attention任意两个词之间的距离都是1,可以直接建立关联;第三,可解释性强,注意力权重矩阵直观展示了词与词之间的关系。实际应用中,比如处理一篇5000字的文章,Transformer能同时关注全文关键信息,而RNN可能已经"忘记"开头的内容了。


【面试题】2. RAG系统中,如何解决检索到的文档与问题不相关的问题?有哪些优化策略? ​

【标准答案】这是RAG系统最常见的问题,优化策略分三个层面。检索层面:第一,混合检索,结合关键词检索(BM25)和向量检索,keyword匹配精确术语,向量匹配语义相似,取交集或加权融合;第二,重排序,先用向量检索召回Top50,再用精细模型如BGE-reranker重新打分取Top5;第三,查询改写,用户问题可能表述模糊,用LLM改写成多个子查询,分别检索后合并。

内容层面:文档切片很关键,固定长度切片可能切断语义,建议按段落或语义边界切分,每块300-500 tokens,保留标题和上下文信息。生成层面:如果检索内容确实不相关,可以设置阈值,让模型直接回答"根据现有知识无法回答",而不是强行编造,这比幻觉好得多。实际项目中,混合检索加重排序能把准确率从60%提到85%以上。


【面试题】3. 什么是Chain of Thought(思维链)提示?它为什么能提升大模型的推理能力?请举例说明。 ​

【标准答案】Chain of Thought是让模型"一步步思考"的提示技巧。核心思想是:不直接问答案,而是要求模型展示推理过程。比如问"一个商店有23个苹果,卖出17个,又进货5个,还剩多少",普通提示直接问可能答错,但加上"请一步步思考"后,模型会先算23-17=6,再算6+5=11,准确率大幅提升。

为什么有效?有两个原因:第一,激活训练数据中学到的推理模式,模型见过大量带步骤的解题过程,CoT提示触发了这种模式;第二,降低错误累积,复杂问题分解成多个小步骤,每步出错概率低,整体准确率自然提高。实际应用中,对于数学推理、逻辑分析、代码生成等任务,CoT能把准确率提升20-40%。高级用法还有Self-Consistency,生成多个CoT路径后投票选答案,进一步提升可靠性。


【面试】4. 设计一个AI Agent系统,让用户能通过自然语言操作数据库查询。请描述核心架构和关键技术点。 ​

【标准答案】我设计一个三阶段架构。第一阶段是意图理解与Schema映射,用户的自然语言问题先经过LLM解析,识别要查询的实体和条件,同时需要把数据库Schema信息注入Prompt,让模型知道有哪些表和字段。关键点是Schema描述要清晰,包括表用途、字段含义、示例数据。

第二阶段是SQL生成与验证,LLM根据Schema生成SQL语句,这里要加两层保障:一是语法检查,用解析器验证SQL是否合法;二是安全审计,禁止DELETE、DROP等危险操作,SELECT和JOIN要有WHERE条件限制。可以维护一个SQL模板库,常见查询复用模板,减少生成错误。

第三阶段是结果解释与追问,查询结果不能直接扔给用户,要用LLM转成自然语言回答,比如"查询到订单总额12.8万元,同比增长15%"。如果结果为空或异常,Agent要主动追问"您是指XXX吗,要不要调整条件"。技术栈推荐LangChain的SQLDatabaseChain,加上Few-Shot示例提升准确率。实际落地中,复杂查询准确率能达到80%,简单查询90%以上。


【面试题】5. 向量数据库中,HNSW和IVF两种索引有什么区别?各自适合什么场景? ​

【标准答案】先说原理。HNSW是层次可导航小世界图,把向量组织成多层图结构,底层是所有向量的精细图,上层是稀疏的跳跃层。查询时从上层粗略定位,逐层向下细化,类似跳表的思想。IVF是倒排文件索引,先用K-Means把向量聚类成若干簇,查询时先找最近的几个簇中心,再在这些簇内暴力搜索。

性能对比:HNSW查询速度更快,通常10-50ms,召回率能达到95%以上,但构建索引慢、内存占用高;IVF构建快、内存省,但查询需要调参(nprobe参数控制搜索多少簇),召回率和速度需要权衡。适用场景:HNSW适合实时性要求高的场景,比如在线推荐、实时检索;IVF适合数据量大、更新频繁、对查询延迟要求不那么极端的场景,比如日志分析、批量检索。

实际项目中,百万级数据用HNSW完全够用,千万级以上、内存受限时IVF更合适。Pinecone、Milvus都支持两种索引,可以先用IVF做召回,再对结果重排序。


【面试题】6. Java中的ThreadLocal是如何实现线程隔离的?什么情况下会导致内存泄漏?如何正确使用? ​

【标准答案】ThreadLocal的核心是每个Thread对象内部维护了一个ThreadLocalMap,这是一个以ThreadLocal对象为key、线程局部变量为value的Map。当你调用threadLocal.set(value),实际上是往当前线程的ThreadLocalMap里存了一组键值对;调用get时,从当前线程的Map里取值,自然就实现了线程隔离。

内存泄漏的原因在于ThreadLocalMap的key是弱引用,但value是强引用。当ThreadLocal对象被回收后,key变成null,但value仍然被Map引用着,如果线程是线程池中的长生命周期线程,这些value对象就会一直存在,造成泄漏。

正确使用的三个要点:第一,务必在finally块中调用remove方法清理,这是强制规范;第二,ThreadLocal尽量声明为static final,避免频繁创建;第三,在Spring等框架中,RequestContextHolder已经帮我们处理好了,但自定义使用时一定要记得清理。实际项目中,我曾经排查过一个生产OOM问题,就是线程池的ThreadLocal没清理,跑了三天后内存爆了。


【面试题】7. CMS和G1垃圾收集器有什么区别?在什么场景下应该选择G1? ​

【标准答案】核心区别有四点。第一,设计目标不同,CMS追求最低停顿时间,G1追求可控停顿时间加高吞吐量,G1可以设置目标停顿时间(-XX:MaxGCPauseTimeMillis)。第二,内存布局不同,CMS是传统分代,Eden、Survivor、Old是连续区域;G1把堆分成多个大小相等的Region,每个Region可以动态扮演不同角色,不再物理隔离。第三,回收方式不同,CMS用标记-清除,会产生内存碎片;G1用复制算法,把存活对象复制到其他Region,天然没有碎片。第四,CMS是Full GC时才回收整个老年代,G1是增量回收,每次只选一部分价值最高的Region。

选择G1的场景:堆内存大于4-6GB,对停顿时间有明确要求,比如要求99%的GC停顿在200ms以内;或者对象存活时间长、内存碎片问题严重的应用。我们线上一个订单系统,堆8GB,从CMS切到G1后,P99延迟从500ms降到了150ms。但要注意,G1在小堆上性能不如CMS,6GB以下还是CMS更合适,JDK9之后G1成为默认收集器。


【面试题】8. Spring Boot的自动装配是如何实现的?@EnableAutoConfiguration注解背后做了什么? ​

【标准答案】Spring Boot自动装配的核心是三点:第一,启动类上的@SpringBootApplication是个组合注解,包含了@EnableAutoConfiguration;第二,@EnableAutoConfiguration通过@Import导入了AutoConfigurationImportSelector,这个Selector会扫描所有jar包下的META-INF/spring.factories文件,加载以EnableAutoConfiguration为key的所有配置类;第三,每个配置类用@Configuration + @Conditional系列注解判断是否生效,比如@ConditionalOnClass检查类路径有没有某个类,@ConditionalOnMissingBean检查容器里是否已存在。

背后的流程是:SpringApplication启动时创建ApplicationContext,刷新上下文时,AutoConfigurationImportSelector被触发,它会先从spring.factories读取所有候选配置类,然后用ImportCandidates过滤,最后交给ConfigurationClassParser解析。每个配置类内部的@Bean方法只有在条件满足时才会注册。

实际开发中,如果想禁用某个自动配置,可以用@SpringBootApplication(exclude={DataSourceAutoConfiguration.class}),或者配置文件里加spring.autoconfigure.exclude。自定义starter时,我们只要写好配置类和spring.factories,就能被自动装配机制发现。


【面试题】9. 一张订单表有5000万数据,查询慢怎么办?请从索引设计、SQL优化、架构层面分别说明。 ​

【标准答案】索引设计层面:首先分析慢查询,确认查询条件和排序字段,建立组合索引。比如查询条件是user_id和create_time,order by create_time desc,索引应该是(user_id, create_time),把等值条件放前面,范围条件放后面。避免select *,只查需要的字段,尽量走覆盖索引。索引不要建太多,单表索引数控制在5个以内,每个索引不超过5列,否则写入性能下降。

SQL优化层面:避免在索引列上做函数操作,比如DATE(create_time)会索引失效;分页查询避免深翻页,limit 1000000, 10要用子查询优化成先查id再关联;大表join改成分批查询,在应用层组装数据。

架构层面:最有效的是分库分表,按user_id分16个库、每个库64张表,单表控制在50万以内;读多写少场景加Redis缓存,热点数据缓存命中率99%以上;历史数据归档,3个月前的数据迁移到历史表或ES,主表保持精简。我们实际项目用ShardingSphere分了32个库,查询从3秒降到了50ms。


【面试题】10. 分布式事务有哪些解决方案?Seata的AT模式是如何保证一致性的?有什么缺点? ​

【标准答案】分布式事务方案主要有四种。第一,2PC/XA,强一致但性能差,锁定资源时间长,适合对一致性要求极高但对性能不敏感的场景。第二,TCC,应用层实现Try-Confirm-Cancel三个接口,性能好但代码侵入性强,适合金融等高可靠场景。第三,本地消息表+最终一致性,写业务数据同时写一条消息记录,定时任务轮询发送,适合异步场景。第四,Seata的AT模式,无侵入的分布式事务框架。

AT模式的原理:一阶段执行SQL时,Seata会解析SQL,记录数据修改前后的快照(before image和after image),写入undo_log表,然后提交本地事务;二阶段全局提交时,异步删除undo_log;全局回滚时,根据undo_log反向生成SQL恢复数据。关键点是通过数据库本地事务保证原子性,用快照实现回滚。

缺点:第一,性能一般,比TCC慢,因为要解析SQL、写undo_log;第二,脏写风险,如果全局事务回滚前,数据被其他事务修改了,回滚会覆盖别人的修改,需要用全局锁解决;第三,不支持的SQL场景,比如存储过程、多表关联更新。实际项目中,电商下单用AT模式完全够用,秒杀这种高性能场景还是TCC或消息队列更合适。


生成完成 | 共10道面试题 | AI方向5道 + Java方向5道