關(guān)于Java中阻塞隊列BlockingQueue的詳解
棧與隊列概念
棧(Stack):先進后出,后進先出
隊列:先進先出
1. 什么是BlockingQueue
在多線程領(lǐng)域:所謂阻塞,在某些情況下會掛起線程(即阻塞),一旦條件滿足,被掛起的線程又會自動被喚起。
BlockingQueue即阻塞隊列,是java.util.concurrent下的一個接口,因此不難理解,BlockingQueue是為了解決多線程中數(shù)據(jù)高效安全傳輸而提出的。從阻塞這個詞可以看出,在某些情況下對阻塞隊列的訪問可能會造成阻塞。被阻塞的情況主要有如下兩種:
- 當隊列滿了的時候進行入隊列操作
- 當隊列空了的時候進行出隊列操作
因此,當一個線程試圖對一個已經(jīng)滿了的隊列進行入隊列操作時,它將會被阻塞,除非有另一個線程做了出隊列操作;同樣,當一個線程試圖對一個空隊列進行出隊列操作時,它將會被阻塞,除非有另一個線程進行了入隊列操作。
阻塞隊列主要用在生產(chǎn)者/消費者的場景,下面這幅圖展示了一個線程生產(chǎn)、一個線程消費的場景:
為什么需要BlockingQueue?
好處是我們不需要關(guān)心什么時候需要阻塞線程,什么時候需要喚醒線程,因為這一切BlockingQueue都給你一手包辦了。在concurrent包發(fā)布以前,在多線程環(huán)境下,我們每個程序員都必須去自己控制這些細節(jié),尤其還要兼顧效率和線程安全,而這會給我們的程序帶來不小的復(fù)雜度。
2. 認識BlockingQueue
java.util.concurrent 包里的 BlockingQueue是一個接口,繼承Queue接口,Queue接口繼承 Collection。
BlockingQueue接口主要有以下7個實現(xiàn)類:
- ArrayBlockingQueue:由數(shù)組結(jié)構(gòu)組成的有界阻塞隊列。
- LinkedBlockingQueue:由鏈表結(jié)構(gòu)組成的有界(但大小默認值為integer.MAX_VALUE)阻塞隊列。
- PriorityBlockingQueue:支持優(yōu)先級排序的無界阻塞隊列。
- DelayQueue:使用優(yōu)先級隊列實現(xiàn)的延遲無界阻塞隊列。
- SynchronousQueue:不存儲元素的阻塞隊列,也即單個元素的隊列。
- LinkedTransferQueue:由鏈表組成的無界阻塞隊列。
- LinkedBlockingDeque:由鏈表組成的雙向阻塞隊列。
BlockingQueue接口有以下幾個方法:它的方法可以分成以下4類:
拋出異常 | 特殊值 | 阻塞 | 超時 | |
插入 | add(e) | offer(e) | put(e) | offer(e, time, unit) |
移除 | remove() | poll() | take() | poll(time, unit) |
檢查 | element() | peek() | 不可用 | 不可用 |
① 拋出異常
add正常執(zhí)行返回true,element(不刪除)和remove返回阻塞隊列中的第一個元素? 當阻塞隊列滿時,再往隊列里add插入元素會拋IllegalStateException:Queue full? 當阻塞隊列空時,再往隊列里remove移除元素會拋NoSuchElementException? 當阻塞隊列空時,再調(diào)用element檢查元素會拋出NoSuchElementException。
② 特定值
插入方法,成功ture失敗false 移除方法,成功返回出隊列的元素,隊列里沒有就返回null 檢查方法,成功返回隊列中的元素,沒有返回null。
③ 一直阻塞
如果試圖的操作無法立即執(zhí)行,該方法調(diào)用將會發(fā)生阻塞,直到能夠執(zhí)行。? 當阻塞隊列滿時,再往隊列里put元素,隊列會一直阻塞生產(chǎn)者線程直到put數(shù)據(jù)or響應(yīng)中斷退出? 當阻塞隊列空時,再從隊列里take元素,隊列會一直阻塞消費者線程直到隊列可用。
④ 超時退出
如果試圖的操作無法立即執(zhí)行,該方法調(diào)用將會發(fā)生阻塞,直到能夠執(zhí)行,但等待時間不會超過給定值。? 返回一個特定值以告知該操作是否成功(典型的是 true / false)。
3. 代碼演示
public class BlockingQueueDemo { public static void main(String[] args) throws InterruptedException { BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); // 第一組方法:add remove element // System.out.println(queue.add("a")); // System.out.println(queue.add("b")); // System.out.println(queue.add("c")); // // System.out.println(queue.add("d")); // // System.out.println(queue.element()); // System.out.println(queue.remove()); // System.out.println(queue.remove()); // System.out.println(queue.remove()); // //System.out.println(queue.remove()); // //System.out.println(queue.element()); // 第二組:offer poll peek // System.out.println(queue.offer("a")); // System.out.println(queue.offer("b")); // System.out.println(queue.offer("c")); // System.out.println(queue.offer("d")); // System.out.println(queue.peek()); // System.out.println(queue.poll()); // System.out.println(queue.poll()); // System.out.println(queue.poll()); // System.out.println(queue.poll()); // System.out.println(queue.peek()); // 第三組:put take // queue.put("a"); // queue.put("b"); // queue.put("c"); // System.out.println(queue.take()); // queue.put("d"); // System.out.println(queue.take()); // System.out.println(queue.take()); // System.out.println(queue.take()); // 第四組:offer poll System.out.println(queue.offer("a")); System.out.println(queue.offer("b")); System.out.println(queue.offer("c")); System.out.println(queue.offer("d", 5, TimeUnit.SECONDS)); } }
到此這篇關(guān)于關(guān)于Java中阻塞隊列BlockingQueue的詳解的文章就介紹到這了,更多相關(guān)Java阻塞隊列BlockingQueue內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java Thread中start()和run()的區(qū)別_動力節(jié)點Java學(xué)院整理
start() : 它的作用是啟動一個新線程,新線程會執(zhí)行相應(yīng)的run()方法。start()不能被重復(fù)調(diào)用。而run() : run()就和普通的成員方法一樣,可以被重復(fù)調(diào)用。下面通過示例代碼給大家介紹了Java Thread中start()和run()的區(qū)別,感興趣的朋友一起看看吧2017-05-05SpringSecurity中內(nèi)置過濾器的使用小結(jié)
SpringSecurity通過其復(fù)雜的過濾器鏈機制,為Java應(yīng)用提供了全面的安全防護,本文主要介紹了SpringSecurity中內(nèi)置過濾器的使用小結(jié),感性的可以了解一下2025-03-03MySQL中關(guān)鍵字UNION和UNION ALL的區(qū)別
本文主要介紹了MySQL中關(guān)鍵字UNION和UNION ALL的區(qū)別,深入探討UNION和UNION ALL的定義、用法、主要區(qū)別,具有一定的參考價值,感興趣的可以了解一下2024-06-06Java GUI進階之流式布局管理器FlowLayout專項精講
FlowLayout-流式布局管理器,按水平方向依次排列放置組件,排滿一行,換下一行繼續(xù)排列。排列方向(左到右 或 右到左)取決于容器的componentOrientation屬性2022-04-04解決Mybatis-plus找不到對應(yīng)表及默認表名命名規(guī)則的問題
這篇文章主要介紹了解決Mybatis-plus找不到對應(yīng)表及默認表名命名規(guī)則的問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-11-11