JUC 阻塞佇列

2021-10-03 16:30:23 字數 3817 閱讀 1573

什麼是阻塞佇列:

阻塞佇列常用於生產者和消費者場景,生產者是向佇列裡新增元素的執行緒,消費者是從佇列裡獲取元素的執行緒。阻塞佇列就是生產者用來存放元素、消費者用來獲取元素的容器

為什麼要使用阻塞佇列: 就是適用在不得不阻塞的場景如上面所說生產者 和 消費者場景中 要是佇列中為空 消費者不得不進行阻塞 佇列滿也是同樣的道理 而且好處是我們不需要關心什麼時候需要阻塞執行緒,什麼時候需要喚醒執行緒,因為這一切blockingqueue都給你一手包辦了 在concurrent包發布以前,在多執行緒環境下,我們每個程式設計師都必須去自己控制這些細節,尤其還要兼顧效率和執行緒安全,而這會給我們的程式帶來不小的複雜度

阻塞佇列的使用:

兩個附加操作的4種處理方式:

法/處理方式

丟擲異常

返回特殊值

一直阻塞

超時退出

插入方法

add(e)

offer(e)

put(e)

offer(time, unit)

移除方法

remove()

poll()

take()

poll(time, unit)

檢查方法

element()

peek()

不可用不可用

阻塞佇列實現類的使用:

塞佇列的是西安類

描述arrayblockingqueue由陣列結構組成的有界阻塞佇列 需要手動的傳入初始長度

linkedblockingqueue有鍊錶結構組成的有界阻塞佇列 (但是預設的初始值為integer.max_value)

priorityblockingqueue

支援優先順序排序的無界阻塞佇列

delayqueue

使用優先順序佇列實現的延遲無界佇列

synchronousqueue不儲存元素的阻塞佇列 也就是單個元素的佇列

linkedtransferqueue

有鍊錶組成的無界阻塞佇列

linkedblockingdeque

有鍊錶組成的雙向阻塞佇列

公平訪問佇列/非公平訪問佇列:

為什麼預設的是使用非公平的形式進行佇列的訪問:為了保證公平性,通常會降低吞吐量。因此,引數fair的預設值為false

公平性是如何實現的:使用的是reentrantlock

通過可重入鎖reentrantlock 不管是向佇列中新增元素,還是獲取元素,都使用先通過lock.lock()加鎖,最後在finally語句塊中通過lock.unlock()解鎖 至於reentrrantlock 加鎖 和 鎖的釋放 在之前 的部落格中有詳細的解釋

public

linkedblockingqueue()

// 預設的是建立乙個初始值為integer.max_value的佇列

public

linkedblockingqueue

(int capacity)

public

linkedblockingqueue

(collection<

?extends

e> c)

佇列中鎖的使用:

linkedblockingqueue有putlock和takelock兩個鎖,都是可重入鎖reentrantlock。當往佇列中新增元素時,使用putlock;從佇列中獲取元素時,使用takelock。都是先進行加鎖(lock()),再在finally方法中進行解鎖(unlock())

priorityblockingqueue是乙個支援優先順序的無界阻塞佇列,預設情況下元素採取自然順序公升序排列。也可以自定義類實現compareto()方法來指定元素排序規則,或者初始化priorityblockingqueue時,指定構造引數comparator來進行排序。但是不能保證同優先順序元素的順序,在scheduledfuturetask中為了避免這種情況,除了依靠time進行優先順序排序,還依靠sequencenumber進行優先順序排序構造方法如下:

public

priorityblockingqueue()

public

priorityblockingqueue

(int initialcapacity)

public

priorityblockingqueue

(collection<

?extends

e> c)

public

priorityblockingqueue

(int initialcapacity, comparator<

?super e> comparator)

public

delayqueue

(collection<

?extends

e> c)

佇列中鎖的使用:

synchronousqueue 是乙個不儲存元素的阻塞佇列也就是說佇列中的元素個數最多只有乙個建構函式如下:

public

synchronousqueue()

public

synchronousqueue

(boolean fair)

詳解:

鎖的使用:

linkedtransferqueue 是乙個用鍊錶實現的的無界阻塞 transferqueue 佇列相對於其他阻塞佇列linkedtransferqueue 多了 transfer()和 trytransfer()方法 構造方法如下:

public

linkedtransferqueue()

public

linkedtransferqueue

(collection<

?extends

e> c)

trytransfer()方法:

linkedblockingdeque 是乙個用鍊錶實現的雙向有界阻塞佇列,可以從佇列的兩端插入和移除元素linkedblockingdeque可以運用在工作竊取模式中 與linkedblockingqueue一樣,預設的長度和最大容量為integer.max_value。雙向佇列由於存在兩個出入口,可以減少多執行緒同時入隊的競爭 構造方法如下:

public

linkedblockingdeque()

public

linkedblockingdeque

(int capacity)

public

linkedblockingdeque

(collection<

?extends

e> c)

5.阻塞佇列的總結

juc 阻塞佇列BlockingQueue

阻塞佇列blockingqueue的方法分類 方法型別 丟擲異常 特殊值阻塞 超時插入 add e offer e put e offer e,time,unit 移除remove poll take poll time,unit 檢查element peek 不可用不可用 丟擲異常 當阻塞佇列滿時...

JUC阻塞佇列BlockingQueue

前言 最近面試和手動建立執行緒池時都用到了阻塞佇列,不由得產生好奇,一下原理 參考 目錄 第一章 基礎使用 第二章 實現原理 2.1 arrayblockingqueue 2.2 linkedblockingqueue 第三章 執行緒池中所之用的阻塞佇列 juc中實現乙個阻塞佇列一般都會實現bloc...

JUC學習 阻塞佇列

在這篇部落格中我們接觸的佇列都是非阻塞佇列,比如priorityqueue linkedlist linkedlist是雙向鍊錶,它實現了dequeue介面 阻塞佇列常用於執行緒池和生產者消費者的問題中 使用非阻塞佇列的時候有乙個很大問題就是 它不會對當前執行緒產生阻塞,那麼在面對類似消費者 生產者...