Java阻塞隊(duì)列必看類:BlockingQueue快速了解大體框架和實(shí)現(xiàn)思路
前言
本文主要說(shuō)明BlockingQueue類、阻塞隊(duì)列使用的共同父類AbstractQueue的基礎(chǔ)知識(shí)。后續(xù)將會(huì)逐漸探索BlockingQueue的所有實(shí)現(xiàn)類。
BlockingQueue
概覽
1. 不接受null元素。
通過(guò)新增方法添加null元素時(shí),會(huì)拋出空指針異常。因?yàn)閚ull值將用作標(biāo)記??值,來(lái)指明poll操作失敗。同時(shí)null值作為阻塞隊(duì)列的元素也是無(wú)任何意義的。
2. 可以有容量限制,也可以沒(méi)有。
當(dāng)作為有界隊(duì)列時(shí),如果當(dāng)隊(duì)列空間不足時(shí),add操作將會(huì)拋出IllegalStateException異常,offer將會(huì)返回false,put操作將會(huì)阻塞直到隊(duì)列空間可用。
如果不設(shè)置容量大小,那么默認(rèn)值是Integer.MAX_VALUE。此時(shí)可以看作無(wú)界隊(duì)列;
雖然隊(duì)列在邏輯上可以是無(wú)界的,但由于資源耗盡(導(dǎo)致OutOfMemoryError ),添加操作可能會(huì)失敗。
3. 用于生產(chǎn)者-消費(fèi)者隊(duì)列,但是同時(shí)也支持Collection的操作。
例如刪除隊(duì)列元素操作remove(e),但是這些操作的效率很低,一般僅用于刪除某個(gè)臨時(shí)取消的任務(wù)。
4. 所有實(shí)現(xiàn)都是線程安全的。
但是對(duì)于集合中的批量操作方法,如果其實(shí)現(xiàn)類沒(méi)有特殊處理的話,那么addAll、containsAll、retainAll、removeAll等可能不會(huì)原子地執(zhí)行。
5. 隊(duì)列,整體上都基本準(zhǔn)尋先進(jìn)先出的訪問(wèn)順序。
在整體上看,各個(gè)實(shí)現(xiàn)類是符合FIFO的順序的。
主要實(shí)現(xiàn)類
LinkedBlockingQueue
:鏈表式阻塞隊(duì)列ArrayBlockingQueue
:數(shù)組式阻塞隊(duì)列PriorityBlockingQueue
:優(yōu)先級(jí)阻塞隊(duì)列LinkedBlockingDeque
:阻塞型雙端隊(duì)列DelayQueue
:延時(shí)阻塞隊(duì)列SynchronousQueue
:實(shí)時(shí)同步隊(duì)列(沒(méi)有任何存儲(chǔ)元素的空間)- …………
BlockingQueue方法的四類形式
BlockingQueue的所有實(shí)現(xiàn)類的方法都分為如下四類。相對(duì)于其他的集合操作方法,put和take是實(shí)現(xiàn)阻塞操作的核心方法,需要重點(diǎn)關(guān)注。
Throws exception
:操作未實(shí)現(xiàn)時(shí)(正常流程下的執(zhí)行)拋出異常Special value
:根據(jù)操作的實(shí)際情況,返回特定值,例如null、falseBlocks
:阻塞當(dāng)前線程,直到當(dāng)前線程可以成功執(zhí)行Times out
:嘗試指定時(shí)間后,放棄執(zhí)行
Throws exception | Special value | Blocks | Times out | |
新增 | add(E e) | offer(E e) | put(E e) | offer(E e, long timeout, TimeUnit unit) |
刪除 | remove() | poll() | take() | poll(long timeout, TimeUnit unit) |
查詢 | element() | peek() |
BlockingQueue類確定了阻塞隊(duì)列的整體框架,確定了各個(gè)方法的定義,因此也是了解阻塞隊(duì)列一定要學(xué)習(xí)的類。
本文中大部分都是從源碼注釋中解讀而來(lái),同時(shí)也包含了一些自己的理解,如果表述有誤,還望指出。
AbstractQueue
概覽
AbstractQueue類,提供了一些Queue操作的骨架實(shí)現(xiàn)。
這里提及AbstractQueue的原因是,阻塞隊(duì)列的大多實(shí)現(xiàn)類都繼承該類,可以說(shuō),這個(gè)抽象類,實(shí)現(xiàn)了BlockingQueue的大部分通用功能。比如add、remove失敗時(shí)拋出異常等等,下面會(huì)一一提及。
源碼解析
這個(gè)類基本上搭建起了一個(gè)阻塞隊(duì)列Throws exception形式的框架,它實(shí)現(xiàn)了各個(gè)拋出異常的方法。
各個(gè)方法都比較簡(jiǎn)單,關(guān)鍵在于了解其具體的實(shí)現(xiàn)思路。這對(duì)了解各個(gè)阻塞隊(duì)列的實(shí)現(xiàn)類很有幫助。
add
? ? public boolean add(E e) { ? ? ? ? if (offer(e)) ? ? ? ? ? ? return true; ? ? ? ? else ? ? ? ? ? ? throw new IllegalStateException("Queue full"); ? ? }
當(dāng)隊(duì)列空間足夠時(shí),將直接插入成功。offer方法由具體的子類實(shí)現(xiàn)。
如果offer插入元素成功,則add返回true ,否則將拋出IllegalStateException異常。
remove
? ? public E remove() { ? ? ? ? E x = poll(); ? ? ? ? if (x != null) ? ? ? ? ? ? return x; ? ? ? ? else ? ? ? ? ? ? throw new NoSuchElementException(); ? ? }
檢索并刪除隊(duì)列的隊(duì)首元素。
它與poll不同之處僅在于,如果此隊(duì)列為空,它會(huì)拋出NoSuchElementException異常。
刪除成功后,返回刪除的元素。
element
? ? public E element() { ? ? ? ? E x = peek(); ? ? ? ? if (x != null) ? ? ? ? ? ? return x; ? ? ? ? else ? ? ? ? ? ? throw new NoSuchElementException(); ? ? }
僅獲取隊(duì)列的隊(duì)首元素并返回結(jié)果,并不進(jìn)行操作。
與peek不同之處在于,如果此隊(duì)列為空,它會(huì)引發(fā)NoSuchElementException異常。
clear
與addAll
? ? public void clear() { ? ? ? ? while (poll() != null) ? ? ? ? ? ? ; ? ? }? ? ? ? public boolean addAll(Collection<? extends E> c) { ? ? ? ? if (c == null) ? ? ? ? ? ? throw new NullPointerException(); ? ? ? ? if (c == this) ? ? ? ? ? ? throw new IllegalArgumentException(); ? ? ? ? boolean modified = false; ? ? ? ? for (E e : c) ? ? ? ? ? ? if (add(e)) ? ? ? ? ? ? ? ? modified = true; ? ? ? ? return modified; ? ? }
遍歷添加或刪除所有元素,實(shí)現(xiàn)挺簡(jiǎn)單的,不過(guò)這里并沒(méi)有進(jìn)行單個(gè)操作出現(xiàn)異常時(shí)的處理。
總結(jié)
阻塞隊(duì)列了解得也差不多了,之前只是簡(jiǎn)單的學(xué)習(xí)了如何使用阻塞隊(duì)列的方法,這次也是打算來(lái)一個(gè)全面深入的學(xué)習(xí)吧。知其然知其所以然,對(duì)于程序員還是蠻重要的。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 關(guān)于Java中阻塞隊(duì)列BlockingQueue的詳解
- Java阻塞隊(duì)列BlockingQueue基礎(chǔ)與使用
- Java阻塞隊(duì)列BlockingQueue詳解
- Java?阻塞隊(duì)列BlockingQueue詳解
- Java并發(fā)編程之阻塞隊(duì)列(BlockingQueue)詳解
- Java源碼解析阻塞隊(duì)列ArrayBlockingQueue介紹
- Java源碼解析阻塞隊(duì)列ArrayBlockingQueue常用方法
- Java源碼解析阻塞隊(duì)列ArrayBlockingQueue功能簡(jiǎn)介
- 詳解Java阻塞隊(duì)列(BlockingQueue)的實(shí)現(xiàn)原理
- java 中 阻塞隊(duì)列BlockingQueue詳解及實(shí)例
- 一文簡(jiǎn)介Java中BlockingQueue阻塞隊(duì)列
相關(guān)文章
Spring中@ExceptionHandler注解的工作原理詳解
這篇文章主要介紹了Spring中@ExceptionHandler注解的工作原理詳解,Spring Web注解@ExceptionHandler可以用來(lái)指定處理某類異常的控制器方法,從而在這些異常發(fā)生時(shí),會(huì)有相應(yīng)的控制器方法來(lái)處理此類異常,需要的朋友可以參考下2024-01-01SpringBoot整合Javamail實(shí)現(xiàn)郵件發(fā)送的詳細(xì)過(guò)程
日常開(kāi)發(fā)過(guò)程中,我們經(jīng)常需要使用到郵件發(fā)送任務(wù),比方說(shuō)驗(yàn)證碼的發(fā)送、日常信息的通知等,下面這篇文章主要給大家介紹了關(guān)于SpringBoot整合Javamail實(shí)現(xiàn)郵件發(fā)送的詳細(xì)過(guò)程,需要的朋友可以參考下2022-10-10java使用CompletableFuture分批處理任務(wù)實(shí)現(xiàn)
本文主要介紹了java使用CompletableFuture分批處理任務(wù)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-07-07SpringBoot多數(shù)據(jù)庫(kù)連接(mysql+oracle)的實(shí)現(xiàn)
這篇文章主要介紹了SpringBoot多數(shù)據(jù)庫(kù)連接(mysql+oracle)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03淺談Spring如何解決循環(huán)依賴的問(wèn)題
這篇文章主要介紹了淺談Spring如何解決循環(huán)依賴的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09使用XML配置c3p0數(shù)據(jù)庫(kù)連接池
這篇文章主要為大家詳細(xì)介紹了使用XML配置c3p0數(shù)據(jù)庫(kù)連接池,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-08-08SpringBoot如何接收Post請(qǐng)求Body里面的參數(shù)
這篇文章主要介紹了SpringBoot如何接收Post請(qǐng)求Body里面的參數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03SpringBoot Shiro配置自定義密碼加密器代碼實(shí)例
這篇文章主要介紹了SpringBoot Shiro配置自定義密碼加密器代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03