Java阻塞隊(duì)列必看類:BlockingQueue快速了解大體框架和實(shí)現(xiàn)思路
前言
本文主要說明BlockingQueue類、阻塞隊(duì)列使用的共同父類AbstractQueue的基礎(chǔ)知識。后續(xù)將會逐漸探索BlockingQueue的所有實(shí)現(xiàn)類。
BlockingQueue
概覽
1. 不接受null元素。
通過新增方法添加null元素時,會拋出空指針異常。因?yàn)閚ull值將用作標(biāo)記??值,來指明poll操作失敗。同時null值作為阻塞隊(duì)列的元素也是無任何意義的。
2. 可以有容量限制,也可以沒有。
當(dāng)作為有界隊(duì)列時,如果當(dāng)隊(duì)列空間不足時,add操作將會拋出IllegalStateException異常,offer將會返回false,put操作將會阻塞直到隊(duì)列空間可用。
如果不設(shè)置容量大小,那么默認(rèn)值是Integer.MAX_VALUE。此時可以看作無界隊(duì)列;
雖然隊(duì)列在邏輯上可以是無界的,但由于資源耗盡(導(dǎo)致OutOfMemoryError ),添加操作可能會失敗。
3. 用于生產(chǎn)者-消費(fèi)者隊(duì)列,但是同時也支持Collection的操作。
例如刪除隊(duì)列元素操作remove(e),但是這些操作的效率很低,一般僅用于刪除某個臨時取消的任務(wù)。
4. 所有實(shí)現(xiàn)都是線程安全的。
但是對于集合中的批量操作方法,如果其實(shí)現(xiàn)類沒有特殊處理的話,那么addAll、containsAll、retainAll、removeAll等可能不會原子地執(zhí)行。
5. 隊(duì)列,整體上都基本準(zhǔn)尋先進(jìn)先出的訪問順序。
在整體上看,各個實(shí)現(xiàn)類是符合FIFO的順序的。
主要實(shí)現(xiàn)類
LinkedBlockingQueue:鏈表式阻塞隊(duì)列ArrayBlockingQueue:數(shù)組式阻塞隊(duì)列PriorityBlockingQueue:優(yōu)先級阻塞隊(duì)列LinkedBlockingDeque:阻塞型雙端隊(duì)列DelayQueue:延時阻塞隊(duì)列SynchronousQueue:實(shí)時同步隊(duì)列(沒有任何存儲元素的空間)- …………
BlockingQueue方法的四類形式
BlockingQueue的所有實(shí)現(xiàn)類的方法都分為如下四類。相對于其他的集合操作方法,put和take是實(shí)現(xiàn)阻塞操作的核心方法,需要重點(diǎn)關(guān)注。
Throws exception:操作未實(shí)現(xiàn)時(正常流程下的執(zhí)行)拋出異常Special value:根據(jù)操作的實(shí)際情況,返回特定值,例如null、falseBlocks:阻塞當(dāng)前線程,直到當(dāng)前線程可以成功執(zhí)行Times out:嘗試指定時間后,放棄執(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ì)列的整體框架,確定了各個方法的定義,因此也是了解阻塞隊(duì)列一定要學(xué)習(xí)的類。
本文中大部分都是從源碼注釋中解讀而來,同時也包含了一些自己的理解,如果表述有誤,還望指出。
AbstractQueue
概覽
AbstractQueue類,提供了一些Queue操作的骨架實(shí)現(xiàn)。
這里提及AbstractQueue的原因是,阻塞隊(duì)列的大多實(shí)現(xiàn)類都繼承該類,可以說,這個抽象類,實(shí)現(xiàn)了BlockingQueue的大部分通用功能。比如add、remove失敗時拋出異常等等,下面會一一提及。
源碼解析
這個類基本上搭建起了一個阻塞隊(duì)列Throws exception形式的框架,它實(shí)現(xiàn)了各個拋出異常的方法。
各個方法都比較簡單,關(guān)鍵在于了解其具體的實(shí)現(xiàn)思路。這對了解各個阻塞隊(duì)列的實(shí)現(xiàn)類很有幫助。
add
? ? public boolean add(E e) {
? ? ? ? if (offer(e))
? ? ? ? ? ? return true;
? ? ? ? else
? ? ? ? ? ? throw new IllegalStateException("Queue full");
? ? }當(dāng)隊(duì)列空間足夠時,將直接插入成功。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ì)列為空,它會拋出NoSuchElementException異常。
刪除成功后,返回刪除的元素。
element
? ? public E element() {
? ? ? ? E x = peek();
? ? ? ? if (x != null)
? ? ? ? ? ? return x;
? ? ? ? else
? ? ? ? ? ? throw new NoSuchElementException();
? ? }僅獲取隊(duì)列的隊(duì)首元素并返回結(jié)果,并不進(jìn)行操作。
與peek不同之處在于,如果此隊(duì)列為空,它會引發(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)挺簡單的,不過這里并沒有進(jìn)行單個操作出現(xiàn)異常時的處理。
總結(jié)
阻塞隊(duì)列了解得也差不多了,之前只是簡單的學(xué)習(xí)了如何使用阻塞隊(duì)列的方法,這次也是打算來一個全面深入的學(xué)習(xí)吧。知其然知其所以然,對于程序員還是蠻重要的。
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
- 關(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功能簡介
- 詳解Java阻塞隊(duì)列(BlockingQueue)的實(shí)現(xiàn)原理
- java 中 阻塞隊(duì)列BlockingQueue詳解及實(shí)例
- 一文簡介Java中BlockingQueue阻塞隊(duì)列
相關(guān)文章
Spring Cloud使用Feign進(jìn)行遠(yuǎn)程調(diào)用的操作指南
本文介紹了Feign作為聲明式HTTP客戶端在SpringCloud中的使用,從簡介、對比RestTemplate的問題、使用步驟,到日志配置、性能優(yōu)化和實(shí)際應(yīng)用進(jìn)行了詳細(xì)講解,包括如何通過Feign簡化接口調(diào)用,以及解決啟動時找不到FeignClient的問題,需要的朋友可以參考下2025-02-02
Java關(guān)鍵字final的實(shí)現(xiàn)原理分析
這篇文章主要介紹了Java關(guān)鍵字final的實(shí)現(xiàn)原理分析,在JDK8之前,如果在匿名內(nèi)部類中需要訪問局部變量,那么這個局部變量一定是final修飾的,但final關(guān)鍵字可以省略,需要的朋友可以參考下2024-01-01
application.yml文件中如何開啟mybatis自動駝峰映射
這篇文章主要介紹了application.yml文件中開啟mybatis自動駝峰映射的方法,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-08-08
Java實(shí)現(xiàn)大文件的分片上傳與下載(springboot+vue3)
這篇文章主要為大家詳細(xì)介紹了java基于springboot+vue3如何大文件的分片上傳與下載,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2023-06-06
tio-boot?jfinal-plugins框架整合redis示例詳解
這篇文章主要為大家介紹了tio-boot?jfinal-plugins框架整合redis示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
Java?數(shù)據(jù)結(jié)構(gòu)與算法系列精講之單向鏈表
單向鏈表特點(diǎn)是鏈表的鏈接方向是單向的,訪問要通過順序讀取從頭部開始。鏈表是使用指針構(gòu)造的列表,是由一個個結(jié)點(diǎn)組裝起來的,又稱為結(jié)點(diǎn)列表。其中每個結(jié)點(diǎn)都有指針成員變量指向列表中的下一個結(jié)點(diǎn),head指針指向第一個結(jié)點(diǎn)稱為表頭,而終止于最后一個指向nuLL的指針2022-02-02
基于Java方式實(shí)現(xiàn)數(shù)據(jù)同步
這篇文章主要為大家詳細(xì)介紹了基于Java方式實(shí)現(xiàn)數(shù)據(jù)同步,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-08-08
java線程Thread.sleep()對比對象的wait示例解析
這篇文章主要為大家介紹了java線程Thread.sleep()對比對象的wait示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09

