由淺入深分析阻塞佇列

2021-10-20 19:31:02 字數 3574 閱讀 7208

arraybolckingqueue

陣列結構組成的有界阻塞佇列。內部構造是陣列,具有陣列的特性。

public

arrayblockingqueue

(int capacity)

public

arrayblockingqueue

(int capacity,

boolean fair)

可以初始化佇列⼤⼩, 且⼀旦初始化不能改變。構造⽅法中的fair表示控制物件的內部鎖是否採⽤公平鎖,預設是⾮公平鎖

linkedblockingqueue

鍊錶結構組成的有界阻塞佇列。具有鍊錶的特性。預設佇列的大小是integer.max_value,也可以指定大小。此佇列按照先進先出的原則對元素進行排序。

public

linkedblockingqueue()

public

linkedblockingqueue

(int capacity)

delayqueue

延遲無界阻塞佇列,該佇列中的元素只有當其指定的延遲時間到了,才能夠從佇列中獲取到該元素。

priorityblockingqueue

基於優先順序的無界阻塞佇列。二叉堆結構。不會阻塞資料生成者(因為佇列是無界的),而只會在沒有可消費的資料時,阻塞資料的消費者。

synchronousqueue

同步佇列,內部容量為0,每個put操作必須等待乙個take操作。cachedthreadpool執行緒池使用。

synchronousqueue 使用cas保證出入佇列執行緒安全,其餘佇列使用reentrantlock保證出入佇列執行緒安全。

利用了lock鎖的多條件(condition)阻塞控制。

通過arrayblockingqueue jdk 1.8 的原始碼來了解原理

首先是構造器,除了初始化佇列的⼤⼩和是否是公平鎖之外,還對同⼀個鎖(lock)初始化了兩個監視器,分別是notemptynotfull。這兩個監視器的作用目前可以簡單理解為標記分組,當該執行緒是put操作時,給他加上監視器notfull,標記這個執行緒是⼀個⽣產者;當執行緒是take操作時,給他加上監視器notempty,標記這個執行緒是消費者。

//資料元素陣列

final object[

] items;

//下⼀個待取出元素索引

int takeindex;

//下⼀個待新增元素索引

int putindex;

//元素個數

int count;

//內部鎖

final reentrantlock lock;

//消費者監視器

private

final condition notempty;

//⽣產者監視器

private

final condition notfull;

public

arrayblockingqueue

(int capacity,

boolean fair)

put操作的原始碼

public

void

put(e e)

throws interruptedexception

finally

}private

void

enqueue

(e x)

總結put的流程:

所有執⾏put操作的執行緒競爭lock鎖,拿到了lock鎖的執行緒進⼊下⼀步,沒有拿到lock鎖的執行緒阻塞等待。

判斷阻塞佇列是否滿了,如果滿了,則調⽤await⽅法阻塞這個執行緒,並標記為notfull(⽣產者)執行緒,同時釋放lock鎖,等待被消費者執行緒喚醒。

如果沒有滿,則調⽤enqueue⽅法將元素put進阻塞佇列。注意這⼀步的執行緒還有⼀種情況是第⼆步中阻塞的執行緒被喚醒且⼜拿到了lock鎖的執行緒。

喚醒⼀個標記為notempty(消費者)的執行緒。

take操作的原始碼

public e take()

throws interruptedexception

finally

}private e dequeue()

總結take的流程

所有執⾏take操作的執行緒競爭lock鎖,拿到了lock鎖的執行緒進⼊下⼀步,沒有拿到lock鎖的執行緒阻塞等待。

判斷阻塞佇列是否為空,如果是空,則調⽤await⽅法阻塞這個執行緒,並標記為notempty(消費者)執行緒,同時釋放lock鎖,等待被⽣產者執行緒喚醒。

如果沒有空,則調⽤dequeue⽅法。注意這⼀步的執行緒還有⼀種情況是第⼆步中阻塞的執行緒被喚醒且⼜拿到了lock鎖的執行緒。

喚醒⼀個標記為notfull(⽣產者)的執行緒。

生產者-消費者模型

public

class

testblockingqueue

class

consumer

implements

runnable

catch

(interruptedexception e)}}

}class

product

implements

runnable

catch

(interruptedexception e)}}

}}

public

class

blockingqueue

public

void

add(t data)

catch

(interruptedexception e)

} list.

add(data)

; emptywaitset.

signal()

;}finally

}public t take()

catch

(interruptedexception e)

} t t = list.

get(0)

; list.

remove(0

);fullwaitset.

signal()

;return t;

}finally

}}

等待佇列 阻塞非阻塞

阻塞 裝置驅動不阻塞,使用者想獲取裝置資源只能不停的查詢,這無謂的消耗cpu資源。而阻塞訪問,不能獲取資源的程序將進入休眠,它將cpu資源 禮讓 給其他程序 喚醒程序的地方最大可能發生在中斷裡面,因為硬體資源獲得的同時往往伴隨著乙個中斷 定義頭 wait queue head t queue 初始化...

由淺入深分析python修飾器

單例模式的設計中有種方法,通過修飾器設計 def singleton cls,args,kw instances defgetinstance if cls not in instances instances cls cls args,kw return instances cls return ...

阻塞佇列BlockingQueue

例介紹乙個特殊的佇列 blockingqueue,如果blockingqueue是空的,從blockingqueue取東西的操作將會被阻斷進入等待狀態,直到blockingqueue進了東西才會被喚醒,同樣,如果blockingqueue是滿的,任何試圖往裡存東西的操作也會被阻斷進入等待狀態,直到b...