ArrayBlockingQueue vs LinkedBlockingQueue,99%的人答不全!
引言
小米最近在刷社招面試題,發(fā)現(xiàn)“ArrayBlockingQueue 和 LinkedBlockingQueue 的區(qū)別”頻繁出現(xiàn)在面試官的題庫里。
作為一名喜歡分享技術的 31 歲“老程序員”,小米覺得有必要深挖一波,順便給大家講講這兩位 Java 并發(fā)容器中的明星選手。畢竟,光會 API 可不夠,面試官喜歡追著問底層原理!
好了,故事開始了!
起源:為什么需要阻塞隊列?
某一天,小米在公司加班,產品經(jīng)理老王突然跑來:“小米,我們的任務隊列經(jīng)常出錯,你看看咋回事?”
小米打開日志一看,原來是有些線程在消費任務的時候隊列為空,導致 NullPointerException,而生產者又可能突然暴增,導致 OutOfMemoryError。
于是,小米一拍腦袋:“這就是典型的生產者-消費者問題,用阻塞隊列就能解決!”
阻塞隊列的作用:
- 生產者-消費者模型:生產者不斷往隊列里放數(shù)據(jù),消費者不斷從隊列取數(shù)據(jù),生產快了隊列會阻塞生產者,消費慢了隊列會阻塞消費者,保證了流量的平穩(wěn)。
- 線程間通信:不需要使用 synchronized 和 wait/notify,內部已經(jīng)封裝好了鎖機制,簡化多線程編程。
- 防止過載:隊列可以設置容量上限,防止生產過快導致 OOM。
java.util.concurrent 包里提供了多個阻塞隊列,今天我們重點講解ArrayBlockingQueue 和 LinkedBlockingQueue,它們是面試中最??嫉膬晌弧袄洗蟾纭薄?/p>
ArrayBlockingQueue:數(shù)組實現(xiàn)的有界隊列
基本特點:
- 基于數(shù)組,底層是 Object[],容量固定(有界隊列)。
- FIFO(先進先出),頭部取數(shù)據(jù),尾部插入數(shù)據(jù)。
- 數(shù)據(jù)結構簡單,內存占用低,適合高性能場景。
- 單一 ReentrantLock 進行并發(fā)控制,鎖粒度大,生產和消費不能同時進行。
源碼解析:
圖片
ArrayBlockingQueue 面試核心點
- 容量固定,創(chuàng)建時必須指定大小,不能動態(tài)擴容。
- 性能較高,但由于采用單一鎖,并發(fā)能力稍差。
- 數(shù)據(jù)存放在數(shù)組中,適合元素數(shù)量穩(wěn)定的場景,避免頻繁擴容帶來的開銷。
LinkedBlockingQueue:鏈表實現(xiàn)的有界/無界隊列
基本特點:
- 基于鏈表,底層是 Node<E> 鏈表,可以是有界隊列(指定大?。┗驘o界隊列(默認 Integer.MAX_VALUE)。
- FIFO(先進先出),頭部取數(shù)據(jù),尾部插入數(shù)據(jù)。
- 雙鎖機制,生產和消費使用不同的 ReentrantLock,并發(fā)能力更強。
- 適合吞吐量要求較高的場景,但鏈表結構可能增加 GC 壓力。
源碼解析:
圖片
LinkedBlockingQueue 面試核心點
- 默認無界,但可以指定大小,防止 OOM。
- 性能更高,采用雙鎖機制,生產者和消費者可以并行執(zhí)行。
- 數(shù)據(jù)存放在鏈表中,適合元素數(shù)量不確定的場景,但鏈表結構可能增加內存開銷和 GC 壓力。
場景對比:哪種更適合你的項目?
圖片
總結選擇指南:
- 數(shù)據(jù)量穩(wěn)定,低延遲需求,選 ArrayBlockingQueue(如高頻交易系統(tǒng))。
- 數(shù)據(jù)量不確定,吞吐量高,選 LinkedBlockingQueue(如日志收集、任務隊列)。
- 避免無界 LinkedBlockingQueue,否則可能導致 OOM。
面試真題實戰(zhàn)
面試題 1:你會怎么選擇 ArrayBlockingQueue 和 LinkedBlockingQueue?
答:
- 數(shù)據(jù)量穩(wěn)定,需要高性能:ArrayBlockingQueue
- 數(shù)據(jù)量不確定,需要高吞吐:LinkedBlockingQueue
- 防止 OOM,使用 LinkedBlockingQueue 時務必指定容量
面試題 2:為什么 LinkedBlockingQueue 并發(fā)能力比 ArrayBlockingQueue 強?
答:
- LinkedBlockingQueue 采用雙鎖機制(生產者和消費者各有一把鎖),生產和消費可并行。
- ArrayBlockingQueue 采用單鎖機制,生產和消費不能并行,導致并發(fā)能力稍遜。
總結
今天,我們通過小米的面試經(jīng)歷,深入解析了 ArrayBlockingQueue 和 LinkedBlockingQueue。面試官愛問的點,我們都幫大家整理好了!
核心記住三點:
- 固定容量 vs 可擴展性:ArrayBlockingQueue 容量固定,LinkedBlockingQueue 可以無界。
- 單鎖 vs 雙鎖:LinkedBlockingQueue 并發(fā)能力更強。
- 適用場景不同:ArrayBlockingQueue 適合高性能場景,LinkedBlockingQueue 適合高吞吐量場景。