阻塞隊列BlockingQueue

一桐猬、常見的BlockingQueue

1. ArrayBlockingQueue

由數(shù)組支持的有界隊列,內(nèi)部維護(hù)一個定長數(shù)組刽肠。
生產(chǎn)者與消費(fèi)者公用同一個鎖控制數(shù)據(jù)同步溃肪。
處理過程:當(dāng)生產(chǎn)者往隊列存放數(shù)據(jù)時免胃,當(dāng)隊列達(dá)到最大容量時才會阻塞生產(chǎn)者隊列,并且喚醒消費(fèi)者惫撰;當(dāng)消費(fèi)者將隊列元素全部取出羔沙,隊列為空時才會阻塞消費(fèi)者,并且喚醒生產(chǎn)者厨钻。
先進(jìn)先出(FIFO)
默認(rèn)非公平鎖扼雏,可指定為公平鎖。
使用Condition的等待/通知機(jī)制夯膀,使得ArrayBlockingQueue的數(shù)據(jù)寫入和獲取操作足夠輕巧诗充,不需分別使用獨(dú)立生產(chǎn)-消費(fèi)鎖

2. LinkedBlockingQueue

由鏈接節(jié)點(diǎn)支持的可選有界隊列,內(nèi)部維護(hù)一個緩沖隊列诱建,由鏈表構(gòu)成蝴蜓。
生產(chǎn)者與消費(fèi)者采用獨(dú)立的鎖控制數(shù)據(jù)同步
處理過程:當(dāng)生產(chǎn)者往隊列存放數(shù)據(jù)時涂佃,只有隊列達(dá)到最大容量時(構(gòu)造函數(shù)指定)励翼,才會阻塞生產(chǎn)者隊列蜈敢,當(dāng)消費(fèi)者從隊列消費(fèi)掉一條數(shù)據(jù)時辜荠,生產(chǎn)者線程會被喚醒。消費(fèi)者同理抓狭,當(dāng)緩沖區(qū)無數(shù)據(jù)時伯病,阻塞,有數(shù)據(jù)時喚醒否过。
:默認(rèn)LinkedBlockingQueue構(gòu)造方法沒有指定容量大小午笛,默認(rèn)無限大Integer.MAX_VALUE,而生產(chǎn)者消費(fèi)者是同時進(jìn)行的苗桂,所以要避免生產(chǎn)者生產(chǎn)速度遠(yuǎn)大于消費(fèi)者消費(fèi)速度的情況药磺,防止堆內(nèi)存耗盡。
先進(jìn)先出(FIFO)
非公平鎖
添加和刪除隊列中的元素的時候煤伟,會創(chuàng)建和銷毀節(jié)點(diǎn)對象癌佩,在高并發(fā)和大量數(shù)據(jù)的時候,GC壓力很大

3. PriorityBlockingQueue

由優(yōu)先級堆支持的無界優(yōu)先級隊列便锨,優(yōu)先級由傳入的Compator決定围辙,內(nèi)部維護(hù)一個數(shù)組。
處理過程:不會阻塞生產(chǎn)者生產(chǎn)數(shù)據(jù)放案,只會在沒有可消費(fèi)的數(shù)據(jù)時姚建,阻塞消費(fèi)者。
:避免生產(chǎn)者生產(chǎn)速度遠(yuǎn)大于消費(fèi)者消費(fèi)速度的情況吱殉,防止堆內(nèi)存耗盡掸冤。
非公平鎖

4. DelayQueue

由優(yōu)先級堆支持的厘托、基于時間的無界調(diào)度隊列
(DelayQueue入隊的對象必須要實現(xiàn)Delayed接口,而Delayed集成自Comparable接口)
處理過程:只有當(dāng)期指定的延遲時間到了,才會從隊列中獲取該元素稿湿。DelayQueue是一個沒有大小限制的隊列催烘,因此往隊列中插入數(shù)據(jù)的操作(生產(chǎn)者)永遠(yuǎn)不會被阻塞,而只有獲取數(shù)據(jù)的操作(消費(fèi)者)才會被阻塞缎罢。
場景
緩存系統(tǒng)的設(shè)計:可以用DelayQueue保存緩存元素的有效期伊群,使用一個線程循環(huán)查詢DelayQueue,一旦能從DelayQueue中獲取元素時策精,表示緩存有效期到了舰始。
定時任務(wù)調(diào)度:使用DelayQueue保存當(dāng)天將會執(zhí)行的任務(wù)和執(zhí)行時間,一旦從DelayQueue中獲取到任務(wù)就開始執(zhí)行咽袜,比如TimerQueue就是使用DelayQueue實現(xiàn)的
非公平鎖

5. SynchronousQueue

無緩沖的阻塞隊列丸卷,不存儲元素。
處理過程
生產(chǎn)者生產(chǎn)操作必須等待一個消費(fèi)操作询刹,否則不能繼續(xù)添加元素谜嫉。
支持公平鎖,非公平鎖

特點(diǎn)
ArrayBlockingQueue
生產(chǎn)者與消費(fèi)者公用一個鎖控制數(shù)據(jù)同步
生產(chǎn)->隊列滿了->阻塞
消費(fèi)->隊列空了->阻塞
生產(chǎn)與消費(fèi)是交替進(jìn)行的凹联,因為是同一把鎖沐兰。
LinkedBlockingQueue
生產(chǎn)者與消費(fèi)者采用獨(dú)立鎖控制數(shù)據(jù)同步
生產(chǎn)->隊列滿了->阻塞
消費(fèi)->隊列空了->阻塞
生產(chǎn)與消費(fèi)是同時進(jìn)行的,有生產(chǎn)就可以消費(fèi)蔽挠。
SynchronousQueue
無緩沖隊列
生產(chǎn)->消費(fèi)(未消費(fèi)則阻塞生產(chǎn))
生產(chǎn)者生產(chǎn)一個必須等待一個消費(fèi)操作住闯,否則不能繼續(xù)添加元素
PriorityBlockingQueue
優(yōu)先級無界隊列,由傳入的Compator決定優(yōu)先級
生產(chǎn)->消費(fèi)->消費(fèi)空了->阻塞
生產(chǎn)不阻塞澳淑,消費(fèi)空了阻塞比原,生產(chǎn)者生產(chǎn)過快容易內(nèi)存耗盡
DelayQueue
基于時間優(yōu)先級的無界隊列,入隊的對象要實現(xiàn)Delayed接口杠巡,該接口實現(xiàn)了Comparable接口
生產(chǎn)->延遲時間到了->消費(fèi)->消費(fèi)空了->阻塞
生產(chǎn)不阻塞量窘,消費(fèi)空了阻塞。定時任務(wù)可基于該隊列處理

二氢拥、阻塞的實現(xiàn)

ReentranLock + Condition 實現(xiàn)隊列的阻塞蚌铜,ReentranLock是鎖,Condition是條件狀態(tài)兄一,通過等待/通知機(jī)制蓝仲,來實現(xiàn)線程之間的通信捷兰。

ReentranLock + Condition的等待/通知機(jī)制和Object的wait()與notify()是類似的励烦,通過synchronized芝发,在鎖中使用wait()與notify()達(dá)到線程之間通信,在ReentranLock的lock()和unlock()之間通過類似的await()和signal()達(dá)到線程之間的通信。

Condition條件隊列
條件隊列是不會被喚醒競爭鎖的耳璧,如果條件隊列的線程需要被喚醒競爭鎖資源需要被轉(zhuǎn)移到CLH等待隊列中才可以成箫。

在阻塞隊列中A調(diào)用put()方法的時候,如果隊列已滿旨枯,則A線程掛起蹬昌,等待恢復(fù),如果B線程調(diào)用take()后攀隔,消耗一個隊列元素后皂贩,會通知put()方法中掛起的A線程,因為這個時候B線程已經(jīng)消耗一個元素可以在向隊列中添加元素昆汹。相反如果隊列一空 B線程調(diào)用tack()方法會阻塞明刷,當(dāng)A線程調(diào)用put()調(diào)用后通知tack()方法中的B線程,有元素可以獲取满粗。這就是阻塞的實現(xiàn)過程辈末。

三、BlockingQueue的核心方法

1. 生產(chǎn)者生產(chǎn)數(shù)據(jù)

boolean add(E e);
將指定的元素插入到此隊列中映皆,如果成功則返回true挤聘,如果當(dāng)前沒有空間可用則拋出IllegalStateException。當(dāng)使用容量受限的隊列時捅彻,通常更可取的做法是使用offer()方法组去。
boolean offer(E e);
將指定的元素插入到此隊列中,如果成功則返回true沟饥,如果當(dāng)前沒有空間可用則返回false添怔。
void put(E e) throws InterruptedException;
將指定的元素插入到此隊列中湾戳,如果當(dāng)前沒有空間則阻塞至有空間可用
boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException;
將指定的元素插入到此隊列中贤旷,如果需要空間可用,則需要等待指定的等待時間砾脑。

2. 消費(fèi)者消費(fèi)數(shù)據(jù)

E take() throws InterruptedException;
獲取隊首元素并刪除幼驶,如當(dāng)前沒有元素則等待至有元素可獲取
E poll(long timeout, TimeUnit unit) throws InterruptedException;
獲取隊首元素并刪除,如果當(dāng)前沒有元素韧衣,則需要等待指定時間
int drainTo();
一次性從隊列中獲取所有可用元素(也可指定個數(shù))盅藻,并將它們添加到給定集合中。此操作可能比重復(fù)輪詢此隊列更有效率畅铭。

參考:https://www.iteye.com/blog/wsmajunfeng-1629354
http://www.reibang.com/p/32665a52eba1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末氏淑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子硕噩,更是在濱河造成了極大的恐慌假残,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異辉懒,居然都是意外死亡阳惹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門眶俩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莹汤,“玉大人,你說我怎么就攤上這事颠印「倭耄” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵线罕,是天一觀的道長荒勇。 經(jīng)常有香客問我,道長闻坚,這世上最難降的妖魔是什么沽翔? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮窿凤,結(jié)果婚禮上仅偎,老公的妹妹穿的比我還像新娘。我一直安慰自己雳殊,他們只是感情好橘沥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著夯秃,像睡著了一般座咆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上仓洼,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天介陶,我揣著相機(jī)與錄音,去河邊找鬼色建。 笑死哺呜,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的箕戳。 我是一名探鬼主播某残,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼陵吸!你這毒婦竟也來了玻墅?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤壮虫,失蹤者是張志新(化名)和其女友劉穎澳厢,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡赏酥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年喳整,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片裸扶。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡框都,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呵晨,到底是詐尸還是另有隱情魏保,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布摸屠,位于F島的核電站谓罗,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏季二。R本人自食惡果不足惜檩咱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望胯舷。 院中可真熱鬧刻蚯,春花似錦、人聲如沸桑嘶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逃顶。三九已至讨便,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間以政,已是汗流浹背霸褒。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留妙蔗,地道東北人傲霸。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像眉反,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子穆役,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容