校招 未知部门 / 后端-Java / 一面

[面试日期] 2026-03-27 [面试时长] 未知
[学校背景] 清华大学 | 985 [学历背景] 未知
[发布人] 面试之星官方收录
<h2>小米 Java 软件开发工程师一面面经</h2> <p><strong>1. 你的项目中使用了消息队列(MQ),如何保证消息的可靠性投递(不丢失)?</strong></p> <ul> <li><strong>回答</strong>:保证可靠性需要从三个阶段入手: 生产者阶段:开启确认机制(如 RabbitMQ 的 Confirm 模式或 RocketMQ 的同步发送)。发送失败时进行重试,或者记录日志入库。MQ 节点阶段:开启持久化(交换机、队列、消息全部持久化到磁盘)。如果是集群环境,使用镜像队列或多副本同步,确保 Leader 宕机后数据不丢。消费者阶段:关闭自动 ACK,改为手动 ACK。只有在业务逻辑处理成功后才返回确认,防止消息在处理中途由于异常丢失。</li> </ul> <p><strong>2. 谈谈 Netty 的高性能架构,为什么它比传统的 Tomcat 连接器更快?</strong></p> <ul> <li><strong>回答</strong>:Netty 采用了主从多线程 Reactor 模型。 非阻塞 IO:利用 Linux 的 epoll 机制,一个线程可以监控成千上万个连接。零拷贝(Zero-Copy):通过 DirectBuffer 直接操作堆外内存,减少内核态与用户态的数据拷贝;使用 CompositeByteBuf 组合数据,避免内存搬移。无锁串行化:消息处理在特定的 EventLoop 线程内完成,避免了多线程竞争锁的开销。</li> </ul> <p><strong>3. Java 中的 </strong><strong><code>String</code></strong><strong> 为什么要设计成不可变的(final)?</strong></p> <ul> <li><strong>回答</strong>: 安全性:String 经常作为 HashMap 的 Key 或网络连接参数,不可变性保证了哈希值的稳定性及代码安全性。常量池优化:由于不可变,多个相同的字符串可以共享同一个物理地址,节省内存。线程安全:不可变对象天生线程安全,无需同步。</li> </ul> <p><strong>4. 详细描述 JVM 的垃圾回收过程,特别是 G1 收集器的 Region 设计。</strong></p> <ul> <li><strong>回答</strong>:G1 取代了物理上的年轻代和老年代划分,改为大小相等的 <strong>Region</strong>。 可预测停顿:G1 会根据用户设定的最大停顿时间,优先回收价值(存活对象少)最大的 Region。回收过程:初始标记(STW)-&gt; 并发标记 -&gt; 最终标记(STW)-&gt; 筛选回收(STW)。优势:由于采用复制算法,Region 级别的整理避免了内存碎片。</li> </ul> <p><strong>5. 什么是“虚假唤醒”(Spurious Wakeup)?在编写 </strong><strong><code>wait/notify</code></strong><strong> 时如何避免?</strong></p> <ul> <li><strong>回答</strong>:虚假唤醒是指线程在没有收到 <code>notify</code> 信号的情况下从 <code>wait</code> 状态中醒来。 避免方法:必须将 wait() 方法放在 while 循环中检查条件,而不是 if 语句中。</li> </ul> <p><strong>6. </strong><strong><code>HashMap</code></strong><strong> 在 JDK 1.8 之后做了哪些优化?为什么 1.7 的版本会产生死循环?</strong></p> <ul> <li><strong>回答</strong>: 1.8 优化:引入红黑树(链表长度 &gt; 8 且数组长度 &gt; 64 时转换),优化查找效率从 O(n) 到 O(log n);扩容时从头插法改为尾插法。死循环原因(1.7):1.7 扩容采用头插法,多线程环境下会导致链表节点的顺序反转,形成环形链表。1.8 尾插法保持了顺序,从而避免了环的产生。</li> </ul> <p><strong>7. 谈谈 </strong><strong><code>CAS</code></strong><strong> 的原理及其带来的 ABA 问题如何解决?</strong></p> <ul> <li><strong>回答</strong>:CAS(Compare And Swap)利用 CPU 的原子指令完成读-改-写。 ABA 问题:一个值从 A 变到 B 再变回 A,CAS 会认为它没变过。解决方法:引入版本号或时间戳。Java 中提供了 AtomicStampedReference 类,每次更新时对比值和版本号。</li> </ul> <p><strong>8. 线程池的 </strong><strong><code>allowCoreThreadTimeOut</code></strong><strong> 参数有什么作用?</strong></p> <ul> <li><strong>回答</strong>:默认情况下,核心线程(CorePoolSize)即使空闲也不会被销毁。开启该参数后,核心线程在空闲时间超过 <code>keepAliveTime</code> 时也会被回收。这在业务波动较大、夜间流量极低的场景下有助于节省服务器资源。</li> </ul> <p><strong>9. </strong><strong><code>volatile</code></strong><strong> 关键字如何保证可见性?它能保证原子性吗?</strong></p> <ul> <li></li> </ul>
AI 推荐面试题