📍 面試公司:美團
🎯 面試崗位: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 后端崗位,可以關注我、留言交流,我會持續整理大廠面經、高頻八股與項目拆解,陪你一起穩穩上岸!