蚂蚁集团 AI应用开发 一面

1. 做一下自我介绍

2. Java 里线程的工作原理,不从 API 角度回答,说一说

线程本质上是操作系统调度的执行单元,在 JVM 里对应一条独立的执行路径。面试里往深一点讲,重点不是 Thread 类怎么用,而是线程和 CPU 时间片、用户态内核态切换、上下文切换成本、工作内存与主内存可见性之间的关系。Java 程序看上去是多个线程在同时执行,真正底层依赖的是操作系统调度器、CPU cache、一致性协议和 JVM 对内存模型的约束。很多并发 bug 并不是“线程不安全”这四个字能概括,而是可见性、原子性和有序性没有同时满足。

3. volatile 到底解决了什么问题,为什么它不是轻量版 synchronized

volatile 解决的是可见性和一定程度上的有序性,不解决复合操作的原子性。也就是说,一个线程修改了被 volatile 修饰的变量,其他线程能尽快看到这个新值,同时 JVM 和 CPU 不会在它周围随意重排关键指令。但像 count++ 这种读-改-写复合操作,哪怕变量是 volatile,多个线程同时执行仍然会丢更新。所以它不是轻量版锁,而更像一种内存语义声明,适合做状态标志、配置刷新和双重检查中的发布控制。

class Switcher {
    private volatile boolean stopped = false;

    public void stop() {
        stopped = true;
    }

    public void run() {
        while (!stopped) {
            // do work
        }
    }
}

4. Lock 锁和 synchronized 真正的差异是什么,为什么有时候明明能用 synchronized 却还要用 Lock

synchronized 是 JVM 原生监视器语义,使用简单,自动释放,适合边界清晰的互斥场景。Lock 则更像可编程的同步器,支持可中断获取、公平策略、超时获取、条件队列和更灵活的组合控制。真正需要 Lock 的场景,往往不是“它性能更高”,而是你需要显式管理竞争行为,比如限时获取锁、多个条件等待队列、或者想在复杂状态机里把加锁和解锁位置拆开。很多高级并发结构最终都不是靠 synchronized 搞定,而是靠 AQS 这类框架抽象出来的同步器。

5. AQS 为什么能成为很多并发组件的底座,它真正抽象了什么

AQS 抽象的不是“锁”本身,而是一个基于状态值和 FIFO 等待队列的同步框架。它用一个 state 表示同步状态,再配合 CAS、入队、阻塞、唤醒,统一承载独占和共享两种获取模式。像 ReentrantLockSemaphoreCountDownLatchReentrantReadWriteLock 都是在这个框架上实现的。AQS 的价值在于把复杂同步逻辑收敛成“尝试获取失败就排队,状态满足后再唤醒重试”的模型,开发者只需要定义状态如何变化,而不用每次都从零手写并发控制。

6. Spring Bean 生命周期如果从容器角度解释,哪些阶段最关键

从容器视角看,Bean 生命周期关键阶段是实例化、属性填充、Aware 回调、前置后置处理器、初始化、使用和销毁。真正面试里更值得讲的是两个扩展点:一个是 BeanPostProcessor,它能在初始化前后介入 Bean,很多代理增强都发生在这里;另一个是循环依赖和提前暴露对象的问题,尤其是单例 Bean 在三级缓存中的处理。理解生命周期,不只是为了背顺序,而是为了知道 AOP、事务、依赖注入和代理对象到底是在什么时机产生的。

7. AOP 原理,别只说动态代理

AOP 底层确实依赖动态代理,但如果只说 JDK 代理和 CGLIB,就太浅了。真正要讲的是容器如何在 Bean 创建过程中识别切面、解析切点、构造 Advisor,再决定对哪些 Bean 创建代理对象。最终业务方法执行时,调用会进入拦截器链,事务、日志、鉴权、限流这些横切逻辑按顺序织入。AOP 不是一个“代理技术点”,而是容器、元数据和责任链一起配合的结果。

@Around("execution(* com.demo.service..*(..))")
public Object around(ProceedingJoinPoint pjp) throws Throwable {
    long start = System.currentTimeMillis();
    try {
        return pjp.proceed();
    } finally {
        System.out.println("cost=" + (System.currentTimeMillis() - start));
    }
}

8. 除了动态代理,线上系统里你还常见哪些设计模式真的有用

真正常见的不是八股里那些“工厂、单例”简单点名,而是模式如何支撑复杂系统演进。比如责任链很适合做请求校验、风控规则、网关过滤器和模型拦截器;模板方法适合统一任务执行框架;策略模式适合优惠、路由、调度和检索算法切换;观察者或发布订阅适合事件驱动链路;状态模式很适合订单流转和审核流程。工程里模式的意义不是答题,而是把变化隔离开,让复杂逻辑不会堆成一个巨型 if-else。

9. 在分布式系统里,A 调 B 时如果 B 异常或者网络抖动,调用方应该怎么处理才算完整

完整处理一定不是“catch 异常然后重试”。先要区分是超时、连接失败、业务失败还是部分成功,因为它们的补救策略完全不同。然后再看请求是否幂等,是否允许重试,重试用固定间隔还是退避策略,是否要做熔断和降级。更难的是处理“调用方没收到成功响应,但下游其实已经成功”的场景,这时候如果没有幂等键和结果查询接口,重试反而可能制造重复副作用。真正成熟的调用治理,核心是失败分类、幂等语义和可观测性。

10. 时序一致性或者幂等控制在订单类系统里一般怎么做

订单系统里幂等不能靠“前端别点两次”这种假设。比较稳的做法是业务请求带幂等键,服务端用唯一约束、幂等表或者状态机收敛重复请求。时序一致性更复杂,因为你可能会遇到“支付成功先到,订单创建确认后到”这种乱序事件,所以核心不是要求所有事件天然有序,而是让状态转移只接受合法前驱。也就是说,不合法的重复、回退和越级迁移都要被拒绝或者忽略。

create table order_idempotent (
    biz_key varchar(64) primary key,
    order_id bigint not null,
    create_time datetime not null
);

11. 多系统下单和支付要保证最终事务一致性,通常怎么落地

分布式事务在线上真正常用的不是强一致两阶段提交,而是最终一致的事件驱动方案。典型做法是订单服务先落本地事务,再通过事务消息或本地消息表把支付事件可靠送出去,支付完成后回写订单状态。整个过程中每一步都要幂等,而且补偿逻辑不能和主逻辑混在一起。最终一致的关键不在“绝不出错”,而在“即使中间某步失败,也总能通过重试和补偿收敛到正确状态”。

12. 用 Kafka 的理由如果不能只说吞吐高,你会怎么答

Kafka 的优势不只是吞吐大,而是它非常适合日志型、事件型、可回放的流式场景。它通过顺序追加写、分区并行、批量传输、页缓存和零拷贝把吞吐做上去,同时又天然支持消费位点、重放和多订阅者模型。和很多传统 MQ 相比,它更像一个分布式提交日志,而不是纯消息投递系统。所以如果场景是实时分析、事件总线、CDC、埋点流和异步解耦,Kafka 会非常顺手;但如果你要的是复杂延迟消息、优先级、严格事务隔离,未必最优。

13. Kafka 为什么能做到高吞吐,瓶颈通常又会出现在哪里

高吞吐来自几个关键点:顺序写磁盘、批量发送与拉取、分区并行、操作系统页缓存、压缩和零拷贝。它避免了大量随机 IO,把磁盘当成顺序日志设备来使用。但线上瓶颈通常不是某一个魔法点失效,而是 Broker 磁盘打满、分区倾斜、消费跟不上、页缓存命中变差、网络带宽不够或者副本同步延迟。很多人只记得 Kafka 快,却忽略了快的前提是访问模式和资源模型匹配。

14. 追踪一次订单状态变更的链路时,如果中间发生数据丢失,你怎么定位

先确定“丢失”是没生产、没投递、没消费、消费失败未补偿,还是已经处理但查询链路看不到。然后按链路把日志、traceId、消息 key、数据库记录、消费位点和告警时间线串起来。真正难的是异步系统里多个环节都可能是最终一致,看上去像丢数据,实际上只是延迟或视图未更新。所以排

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

AI-Agent面试实战专栏 文章被收录于专栏

本专栏聚焦 AI-Agent 面试高频考点,内容来自真实面试与项目实践。系统覆盖大模型基础、Prompt工程、RAG、Agent架构、工具调用、多Agent协作、记忆机制、评测、安全与部署优化等核心模块。以“原理+场景+实战”为主线,提供高频题解析、标准答题思路与工程落地方法,帮助你高效查漏补缺.

全部评论
看着总结的很好呢
点赞 回复 分享
发布于 04-18 22:24 北京

相关推荐

感觉面完人都通透了,还是太菜了,下去沉淀一下1.redis和lua实现库存防超卖和一人一单,redis用lua的方式和使用2.redis本身的事务特性的方式的区别是什么?为什么不用redis本身的事务特性做防超卖?3.redis的set、get是原子性操作吗?用redis的set已经是原子性的了,为什么还需要使用lua脚本4.lua脚本过长会导致阻塞吗?5.怎么解决实际生产环境中防超卖导致的并发的吞吐量的问题呢?lua会阻塞,那怎么解决既要保证不重复下单又要保证吞吐量6.如果下单的时候,有一个单子在lua中判断秒杀资格卡了很长时间,其他人操作点都点不了 ,会出现这种情况吗7.如果lua脚本中某一步出错异常了会怎么办8.lua脚本写了哪些功能9.布隆过滤器是怎么拦截无效查询的10.volatile关键字作用11.Lock锁的实现原理12.AQS原理13.spring的AOP原理是什么?14.如果是分布式系统,怎么解决分布式系统的事务一致性15.如果用消息队列,如果有一条消息没有及时处理,可能是对堆积了也可能是消息发送给系统但是系统繁忙给丢弃了,你会怎么做16.如果服务器处理任务有上限,不能及时处理新的消息,从消费者来说应该做什么处理17.如果系统繁忙,支付消息丢失了,客户没付钱,但是订单创建成功了,应该怎么后续弥补18.如果lua脚本中有abc三步操作,如果a成功b失败,工程层面上来讲系统应该怎么设计,怎么保证系统的鲁棒性?19.生产环境中抢一笔订单,抢到了但是因为系统的问题内部要做abc三个操作,在做b的时候可能网络抖了一下导致b操作异常,这时候要让客户重新点击一次吗?20.智能客服,使用redis支持会话记忆,agent中会话记忆有几种记忆管理?21.向量数据库中怎么保证获取到的数据是尽量有效且准确的,而不是一些无用的数据22.用向量相似性完成rag召回一般用什么算法23.你了解skill吗?自己写过吗?24.有prompt,为什么引入skill处理25.Ai coding用过吗?ai coding现在有个spec coding,sdd的研发模式,这是一种什么样的概念26.你现在用的ai coding工具有哪些
查看25道真题和解析
点赞 评论 收藏
分享
05-02 22:50
门头沟学院 Java
继续来分享下最近的面经~欢迎友好讨论,信息共享1.实习拷打2.你刚刚说用AI写的那套东西,能介绍一下你具体做了什么?从AI写代码到交付,整个流程是怎么弄的?3.你的项目有前后端吗?大概结构是怎样的?怎么让AI帮你搞出一套能线上正式运行交付的东西?4.你实现这个项目涉及到哪些应用、中间件组件?我需要你说明系统设计的技术选型、底层逻辑,比如爬取后做什么,完整的业务流程讲清楚。5.如果是公司里的实际场景,比如有几十个应用,涉及前端、后端系统,要改一个需求可能需要改多个系统,你让AI怎么处理?6.你用的是什么模型?7.做这个项目消耗了多少token?8.开发中token很昂贵,节省token有哪些方式?9.SDD/TDD这块了解吗?10.那你知道创建一个skill有哪些方式吗?除了自然语言描述,还有什么方式?11.说一说你对function calling的理解。12.function calling和MCP相比,是不是可以没有MCP?13.MCP和客户端通信有几种方式?你怎么配置MCP?14.function calling是通过什么告诉大模型有哪些工具可用?15.大模型使用MCP调用查询天气工具,整个交互流程大概是怎样的?不用太细。16.笔试的时候,你是怎么和系统交互的?没改代码吗?17.你怎么确保AI写的代码没问题?用的是单agent吗?18.单agent和多agent相比,多agent的优势在哪里?19.能用英文口语说1分钟左右吗?20.你平时用的数据库是MySQL吧?如果线上数据量特别大,分页查询变慢,拿到这个优化任务,你的操作步骤是怎样的?21.如果单纯是数据量大导致深度分页查询慢,优化思路是什么?22.MySQL的索引结构你了解吗?为什么是B+树,而不是红黑树、平衡二叉树或者哈希结构?23.HashMap的1.8和1.7相比,做了哪些优化?24.除了结构和插入方式,还有其他优化吗?为什么插入方式会不一样?25.线程池用过吧?它的核心参数有哪些?原理是怎样的?26.Redis你使用了哪些场景?怎么实现的?27.Redis实现分布式锁的原理是什么?28.如果锁的过期时间是1分钟,任务还没执行完,其他人会不会抢锁?29.(看门狗机制下)如果任务一直卡住,其他人是不是都拿不到锁?
查看28道真题和解析
点赞 评论 收藏
分享
评论
1
5
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务