小米 Java 软件开发工程师一面面经

1. 你的项目中使用了消息队列(MQ),如何保证消息的可靠性投递(不丢失)?

  • 回答:保证可靠性需要从三个阶段入手: 生产者阶段:开启确认机制(如 RabbitMQ 的 Confirm 模式或 RocketMQ 的同步发送)。发送失败时进行重试,或者记录日志入库。MQ 节点阶段:开启持久化(交换机、队列、消息全部持久化到磁盘)。如果是集群环境,使用镜像队列或多副本同步,确保 Leader 宕机后数据不丢。消费者阶段:关闭自动 ACK,改为手动 ACK。只有在业务逻辑处理成功后才返回确认,防止消息在处理中途由于异常丢失。

2. 谈谈 Netty 的高性能架构,为什么它比传统的 Tomcat 连接器更快?

  • 回答:Netty 采用了主从多线程 Reactor 模型。 非阻塞 IO:利用 Linux 的 epoll 机制,一个线程可以监控成千上万个连接。零拷贝(Zero-Copy):通过 DirectBuffer 直接操作堆外内存,减少内核态与用户态的数据拷贝;使用 CompositeByteBuf 组合数据,避免内存搬移。无锁串行化:消息处理在特定的 EventLoop 线程内完成,避免了多线程竞争锁的开销。

3. Java 中的 String 为什么要设计成不可变的(final)?

  • 回答: 安全性:String 经常作为 HashMap 的 Key 或网络连接参数,不可变性保证了哈希值的稳定性及代码安全性。常量池优化:由于不可变,多个相同的字符串可以共享同一个物理地址,节省内存。线程安全:不可变对象天生线程安全,无需同步。

4. 详细描述 JVM 的垃圾回收过程,特别是 G1 收集器的 Region 设计。

  • 回答:G1 取代了物理上的年轻代和老年代划分,改为大小相等的 Region。 可预测停顿:G1 会根据用户设定的最大停顿时间,优先回收价值(存活对象少)最大的 Region。回收过程:初始标记(STW)-> 并发标记 -> 最终标记(STW)-> 筛选回收(STW)。优势:由于采用复制算法,Region 级别的整理避免了内存碎片。

5. 什么是“虚假唤醒”(Spurious Wakeup)?在编写 wait/notify 时如何避免?

  • 回答:虚假唤醒是指线程在没有收到 notify 信号的情况下从 wait 状态中醒来。 避免方法:必须将 wait() 方法放在 while 循环中检查条件,而不是 if 语句中。

6. HashMap 在 JDK 1.8 之后做了哪些优化?为什么 1.7 的版本会产生死循环?

  • 回答: 1.8 优化:引入红黑树(链表长度 > 8 且数组长度 > 64 时转换),优化查找效率从 O(n) 到 O(log n);扩容时从头插法改为尾插法。死循环原因(1.7):1.7 扩容采用头插法,多线程环境下会导致链表节点的顺序反转,形成环形链表。1.8 尾插法保持了顺序,从而避免了环的产生。

7. 谈谈 CAS 的原理及其带来的 ABA 问题如何解决?

  • 回答:CAS(Compare And Swap)利用 CPU 的原子指令完成读-改-写。 ABA 问题:一个值从 A 变到 B 再变回 A,CAS 会认为它没变过。解决方法:引入版本号或时间戳。Java 中提供了 AtomicStampedReference 类,每次更新时对比值和版本号。

8. 线程池的 allowCoreThreadTimeOut 参数有什么作用?

  • 回答:默认情况下,核心线程(CorePoolSize)即使空闲也不会被销毁。开启该参数后,核心线程在空闲时间超过 keepAliveTime 时也会被回收。这在业务波动较大、夜间流量极低的场景下有助于节省服务器资源。

9. volatile 关键字如何保证可见性?它能保证原子性吗?

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

Java面试圣经 文章被收录于专栏

Java面试圣经,带你练透java圣经

全部评论
同学~考虑投递一下pdd哈,还在持续招聘中,我们组是基础电商交易组,负责平台订单、用户、评价等基础核心功能,校招和实习都有!我主页可以投递
点赞 回复 分享
发布于 04-11 11:00 上海

相关推荐

04-15 13:06
门头沟学院 Java
1.Java 有哪些基本数据类型?2.char 类型占几个字节?3.基本数据类型和包装类有什么区别?4.Java 中常用的集合类有哪些?5.HashSet 的底层数据结构是怎样的?6.HashMap 的 put 方法执行过程是怎样的?7.HashMap 中判断 Key 相等是通过什么方式?8.Java 中的 equals 和 == 有什么区别?9.HashMap 扩容时是怎么处理的?10.扩容后,原数组下标和新数组下标有什么对应关系?11.高低位是如何判断的?12.多线程与并发 (JUC)Java 中加锁的方式有哪些?13.synchronized 和 ReentrantLock 有什么区别?14.ReentrantLock 的公平锁和非公平锁在实现上有什么区别?15.synchronized 的锁升级过程是怎样的?16.锁可以降级吗?17.线程池执行任务的流程是怎样的?18.核心线程数满了之后,为什么先放入队列,而不是直接启动非核心线程?19.核心线程可以被销毁吗?20.线程在执行任务过程中抛出异常会有什么影响?21.InnoDB 的事务隔离级别有哪些?22.可重复读(RR)是通过什么机制实现的?23.MVCC 的原理是什么?24. 结合索引查询、Read View 和 Undo Log,详细讲讲查询一条数据版本的全过程。25.InnoDB 索引的数据结构是怎样的?26.B+ 树和 二叉树有什么区别?27.MVCC 加临键锁)能彻底解决幻读问题吗?28.举个无法解决的 Case。29.间隙锁在 RC(读已提交)和 RR(可重复读)级别下有什么区别?30.Redis 的 IO 模型是怎样的?31.Redis 6.0 之后引入多线程的作用是什么?32.Redis 中的大 Key 需要怎么去删除?33.Redis 内存不足时的淘汰策略有哪些?34.如何用 Java 设计一个 LRU 缓存,实现 O(1) 的查询和修改?35.第一段实习经历的离职原因是什么?36.在运维平台项目中,负责了哪些功能,解决了什么问题?37.通过 Dubbo Filter 记录慢请求日志的具体实现细节是什么?38.Dubbo Filter 的设计模式是什么?39.如何从全局视角统计慢请求(例如按时间段、高频接口 Top 排行)?40.是否有接入完整的监控大盘?41.项目中遇到过哪些棘手的技术问题?42.如果定时同步 Redis 的过程失败了,有什么告警和重试的策略?43.平时编程会使用 AI 工具吗?44.使用什么工具和模型?45.AI 生成代码和手敲代码的比例大概是多少?46.AI 领域的 MCP 协议和 Agent Skills 概念有什么区别?
点赞 评论 收藏
分享
评论
2
8
分享

创作者周榜

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