📍 面试公司:美团
🎯 面试岗位:Java后端开发工程师
📞 面试形式:电话面试
🕒 面试时长:约 50 分钟
🔁 面试轮次:第一轮技术面
✨ 面试整体节奏:
这场美团 Java 一面属于“广度覆盖+重点深挖”的类型,基础知识问得细致,例如 TCP 的可靠机制、线程私有变量、CAS 弱点等,同时还穿插设计模式、Redis 内核、慢 SQL 优化思路等多方面内容。最后加了一道手撕变式题,整体节奏偏快,面试官追问比较多,建议提前熟悉面试项目中你主动提到的关键词。
✅ 面试题目逐题整理与解析:
1. 请做一个简短的自我介绍
考察点:沟通能力、项目整体概况
2. TCP 和 UDP 有什么区别?
考察点:网络协议基础
答案:
- TCP 面向连接,可靠,顺序,基于字节流
- UDP 无连接,不保证可靠性、顺序,基于报文
3. TCP 和 UDP 分别适用于哪些场景?
考察点:协议应用理解
答案:
- TCP:文件传输、HTTP 请求、数据库连接等要求可靠性的场景
- UDP:视频直播、DNS、语音通话等对速度要求高但可容忍部分丢包的场景
4. TCP 如何实现可靠性?
考察点:协议细节理解
答案:
- 三次握手、四次挥手
- 滑动窗口
- ACK 确认机制
- 超时重传
- 校验和
- 流量控制(基于窗口)
- 拥塞控制(慢启动、拥塞避免、快重传、快恢复)
5. 流量控制 vs 拥塞控制的区别?
考察点:网络层协议细节辨析
答案:
- 流量控制:防止接收方来不及处理(接收方能力)
- 拥塞控制:防止网络过载(网络本身能力)
6. 进程和线程的区别是什么?
考察点:操作系统基础
答案:
- 进程:资源分配单位,拥有独立地址空间
- 线程:调度单位,同一进程下线程共享资源,切换开销小
7. 线程如何维护私有变量?
考察点:线程隔离技术
答案:
通过 ThreadLocal
实现线程内变量隔离,不同线程访问的是独立副本。
8. ThreadLocal 的底层原理是什么?会不会造成内存泄漏?
考察点:源码理解、JVM 内存管理
答案:
- 每个线程维护一个
ThreadLocalMap
,Key 是弱引用 - 如果不手动调用
remove()
,会导致 Value 无法被回收,从而内存泄漏
9. 如何避免 ThreadLocal 的内存泄漏?
答案:
- 每次使用后及时调用
remove()
方法 - 尽量使用自动清理机制(如在 try-finally 中清除)
10. synchronized 的底层原理是什么?
考察点:JVM 同步机制
答案:
依赖对象头的 Monitor,底层依赖 JVM 的 monitorenter/monitorexit
指令。加锁过程可能涉及偏向锁、轻量级锁和重量级锁的升级过程。
11. synchronized 有哪些锁优化手段?
答案:
- 偏向锁
- 轻量级锁
- 自旋锁
- 锁粗化、锁消除等编译期优化
12. CAS 是什么?它有哪些缺点?
考察点:无锁编程思想
答案:
- Compare-And-Swap,用于原子操作
- 缺点包括:ABA 问题、只能一个变量、循环开销大
- 可通过版本号、
AtomicStampedReference
解决 ABA 问题
13. 提交任务到线程池后是怎么执行的?
考察点:线程池执行流程
答案:
线程池执行步骤大致如下:
- 判断核心线程是否已满
- 如果未满则新建线程执行任务
- 如果满了就入队等待
- 队列满则判断是否可以创建非核心线程
- 若不能则执行拒绝策略
14. 核心线程数、最大线程数怎么设置?
答案:
- CPU 密集型:核心线程数 = 核心数 + 1
- IO 密集型:核心线程数 = 核心数 / (1 - 阻塞系数) ≈ 核心数 * 2 ~ 5
15. 为什么设置线程池核心线程数要考虑 CPU 核心数?
答案:
为了最大化利用 CPU,不让线程过多导致上下文切换,也不浪费资源。
16. 哪些字段不适合建索引?
考察点:索引使用原则
答案:
- 频繁更新的字段
- 重复率高的字段(如性别)
- 长文本字段(如 text、blob)
- 不参与查询条件的字段
17. 如何优化慢 SQL?
考察点:数据库调优实操
答案:
- 使用合适索引
- 避免 select *
- 使用覆盖索引
- 减少 join 数量
- 查看执行计划(
EXPLAIN
)
18. 什么是索引下推?
考察点:MySQL 查询优化细节
答案:
从 MySQL 5.6 开始,支持将查询条件下推至存储引擎层进行过滤,减少回表,提高查询效率。
19. Redis 的 ZSet 是怎么实现的?
答案:
ZSet(有序集合)底层由 跳表 + Hash 表 组成:跳表负责排序结构,Hash 表提供快速定位。
20. 什么是跳表?
考察点:高级数据结构
答案:
跳表通过多层链表提高查找效率,时间复杂度 O(log n),空间复杂度 O(n),比红黑树实现简单,适合有序结构需求场景。
21. Redis 的过期删除策略有哪些?
答案:
- 定期删除(定时扫描)
- 惰性删除(访问时发现已过期)
- 内存淘汰策略(如 LRU、LFU)
22. Redis 为何这么快?
答案:
- 基于内存存储
- 单线程模型避免锁竞争
- 高效的数据结构
- 多路复用 IO
23. Redis 是单线程的,为什么还能高性能?
答案:
- 只在主线程处理请求,避免加锁开销
- IO 多路复用处理高并发
- 大部分操作是 O(1),延迟低
24. 什么是 IO 多路复用?Redis 怎么用的?
答案:
- 一种让单线程监听多个 socket 的技术(select、epoll)
- Redis 使用
epoll
(Linux)实现事件驱动机制处理并发连接
25. 项目相关内容介绍
考察点:项目深度、技术选型、问题解决思路
建议: 突出业务目标、性能优化、分布式处理等关键词,便于面试官引申提问。
26. 手撕算法:LeetCode 第 2 题变式(链表加法变减法)
考察点:链表操作、边界处理
原题:两数相加(https://leetcode.cn/problems/add-two-numbers/)
面试中变为了“链表减法”,逻辑类似但需要处理借位问题
// 假设两个链表 l1、l2 表示两个正整数,返回 l1 - l2 的结果,数字倒序存储
public ListNode subtractTwoNumbers(ListNode l1, ListNode l2) {ListNode dummy = new ListNode(0), curr = dummy;int borrow = 0;while (l1 != null || l2 != null) {int x = l1 != null ? l1.val : 0;int y = l2 != null ? l2.val : 0;int diff = x - y - borrow;if (diff < 0) {diff += 10;borrow = 1;} else {borrow = 0;}curr.next = new ListNode(diff);curr = curr.next;if (l1 != null) l1 = l1.next;if (l2 != null) l2 = l2.next;}return dummy.next;
}
🧾 总结 & 面试复盘:
这场美团一面涵盖了以下重点模块:
模块 | 关键词 |
---|---|
网络 | TCP、UDP、IO 多路复用、可靠机制 |
并发 | ThreadLocal、synchronized、CAS、线程池执行流程 |
数据库 | 索引优化、慢 SQL、索引下推 |
Redis | 跳表、ZSet、过期删除、多路复用 |
设计模式 | 观察者模式、策略模式(未展开但建议准备) |
手撕代码 | 链表处理能力,变式适应能力 |
建议在准备社招时,深入掌握项目中的关键技术点,并根据关键词延伸到基础原理,这样更容易应对面试官的追问。
📢 最后:
如果你也在准备 Java 后端岗位,可以关注我、留言交流,我会持续整理大厂面经、高频八股与项目拆解,陪你一起稳稳上岸!