Java的堵塞隊列BlockingQueue詳解
一、簡介
阻塞隊列(BlockingQueue)是一個支持兩個附加操作的隊列。
這兩個附加的操作支持阻塞的插入和移除方法。
1)支持阻塞的插入方法:意思是當(dāng)隊列滿時,隊列會阻塞插入元素的線程,直到隊列不滿。
2)支持阻塞的移除方法:意思是在隊列為空時,獲取元素的線程會等待隊列變?yōu)榉强铡?/p>
阻塞隊列常用于生產(chǎn)者和消費者的場景,生產(chǎn)者是向隊列里添加元素的線程,消費者是從隊列里取元素的線程。
阻塞隊列就是生產(chǎn)者用來存放元素、消費者用來獲取元素的容器。
二、BlockingQueue接口提供的方法
1.異常:
是指當(dāng)阻塞隊列滿時候,再往隊列里插入元素,會拋出IllegalStateException("Queuefull")異常。當(dāng)隊列為空時,從隊列里獲取元素時會拋出NoSuchElementException異常。
2.返回特殊值:
插入方法會返回是否成功,成功則返回true。移除方法,則是從隊列里拿出一個元素,如果沒有則返回null
3.一直阻塞:
當(dāng)阻塞隊列滿時,如果生產(chǎn)者線程往隊列里put元素,隊列會一直阻塞生產(chǎn)者線程,直到拿到數(shù)據(jù),或者響應(yīng)中斷退出。當(dāng)隊列空時,消費者線程試圖從隊列里take元素,隊列也會阻塞消費者線程,直到隊列可用。
4.超時退出:
當(dāng)阻塞隊列滿時,隊列會阻塞生產(chǎn)者線程一段時間,如果超過一定的時間,生產(chǎn)者線程就會退出。
BlockingQueue接口源碼
public interface BlockingQueue<E> extends Queue<E> { //將給定元素設(shè)置到隊列中,如果設(shè)置成功返回true, 否則拋出異常。如果是往限定了長度的隊列中設(shè)置值,推薦使用offer()方法。 boolean add(E e); //將給定的元素設(shè)置到隊列中,如果設(shè)置成功返回true, 否則返回false. e的值不能為空,否則拋出空指針異常。 boolean offer(E e); //將元素設(shè)置到隊列中,如果隊列中沒有多余的空間,該方法會一直阻塞,直到隊列中有多余的空間。 void put(E e) throws InterruptedException; //將給定元素在給定的時間內(nèi)設(shè)置到隊列中,如果設(shè)置成功返回true, 否則返回false. boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException; //從隊列中獲取值,如果隊列中沒有值,線程會一直阻塞,直到隊列中有值,并且該方法取得了該值。 E take() throws InterruptedException; //在給定的時間里,從隊列中獲取值,如果沒有取到會拋出異常。 E poll(long timeout, TimeUnit unit) throws InterruptedException; //獲取隊列中剩余的空間。 int remainingCapacity(); //從隊列中移除指定的值。 boolean remove(Object o); //判斷隊列中是否擁有該值。 public boolean contains(Object o); //將隊列中值,全部移除,并發(fā)設(shè)置到給定的集合中。 int drainTo(Collection<? super E> c); //指定最多數(shù)量限制將隊列中值,全部移除,并發(fā)設(shè)置到給定的集合中。 int drainTo(Collection<? super E> c, int maxElements); }
三、Java里的阻塞隊列
JDK提供了7個阻塞隊列,如下。
1.ArrayBlockingQueue是一個用數(shù)組實現(xiàn)的有界阻塞隊列,此隊列按照先進(jìn)先出(FIFO)的原則對元素進(jìn)行排序。支持公平鎖和非公平鎖。
【注:每一個線程在獲取鎖的時候可能都會排隊等待,如果在等待時間上,先獲取鎖的線程的請求一定先被滿足,那么這個鎖就是公平的。反之,這個鎖就是不公平的。公平的獲取鎖,也就是當(dāng)前等待時間最長的線程先獲取鎖】
2.LinkedBlockingQueue
LinkedBlockingQueue:一個由鏈表結(jié)構(gòu)組成的有界隊列,此隊列的長度為Integer.MAX_VALUE。此隊列按照先進(jìn)先出的順序進(jìn)行排序
3.PriorityBlockingQueue
一個支持線程優(yōu)先級排序的無界隊列,默認(rèn)自然序進(jìn)行排序,也可以自定義實現(xiàn)compareTo()方法來指定元素排序規(guī)則,不能保證同優(yōu)先級元素的順序。
4.DelayQueue
一個實現(xiàn)PriorityBlockingQueue實現(xiàn)延遲獲取的無界隊列,在創(chuàng)建元素時,可以指定多久才能從隊列中獲取當(dāng)前元素。只有延時期滿后才能從隊列中獲取元素。(DelayQueue可以運用在以下應(yīng)用場景:
1.緩存系統(tǒng)的設(shè)計:可以用DelayQueue保存緩存元素的有效期,使用一個線程循環(huán)查詢DelayQueue,一旦能從DelayQueue中獲取元素時,表示緩存有效期到了。
2.定時任務(wù)調(diào)度。使用DelayQueue保存當(dāng)天將會執(zhí)行的任務(wù)和執(zhí)行時間,一旦從DelayQueue中獲取到任務(wù)就開始執(zhí)行,從比如TimerQueue就是使用DelayQueue實現(xiàn)的。)
5.SynchronousQueue
一個不存儲元素的阻塞隊列,每一個put操作必須等待take操作,否則不能添加元素。支持公平鎖和非公平鎖。SynchronousQueue的一個使用場景是在線程池里。Executors.newCachedThreadPool()就使用了SynchronousQueue,這個線程池根據(jù)需要(新任務(wù)到來時)創(chuàng)建新的線程,如果有空閑線程則會重復(fù)使用,線程空閑了60秒后會被回收。
6.LinkedTransferQueue
一個由鏈表結(jié)構(gòu)組成的無界阻塞隊列,相當(dāng)于其它隊列,LinkedTransferQueue隊列多了transfer和tryTransfer方法。
7.LinkedBlockingDeque
一個由鏈表結(jié)構(gòu)組成的雙向阻塞隊列。隊列頭部和尾部都可以添加和移除元素,多線程并發(fā)時,可以將鎖的競爭最多降到一半。
到此這篇關(guān)于Java的堵塞隊列BlockingQueue詳解的文章就介紹到這了,更多相關(guān)BlockingQueue堵塞隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Springboot Redis?哨兵模式的實現(xiàn)示例
本文主要介紹了Springboot Redis?哨兵模式的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-01-01Java序列化框架Kryo高效轉(zhuǎn)換對象為字節(jié)流面試精講
這篇文章主要為大家介紹了Java序列化框架Kryo高效轉(zhuǎn)換對象為字節(jié)流面試精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10Springboot導(dǎo)入本地jar后 打包依賴無法加入的解決方案
這篇文章主要介紹了Springboot導(dǎo)入本地jar后 打包依賴無法加入的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11springboot實現(xiàn)上傳并解析Excel過程解析
這篇文章主要介紹了springboot實現(xiàn)上傳并解析Excel過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09Springboot實現(xiàn)XSS漏洞過濾的示例代碼
這篇文章主要介紹了Springboot實現(xiàn)XSS漏洞過濾的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01Spring Boot2配置Swagger2生成API接口文檔詳情
這篇文章主要介紹了Spring Boot2配置Swagger2生成API接口文檔詳情,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-09-09