面試準備,無法保證理解正確性,慎,歡迎糾正併發佇列與普通佇列的區別的確就在於併發二字,而併發的的基礎就是執行緒安全,如何實現執行緒安全是我們最重要的需要理解的部分.執行緒安全的保證無非就是可見性和原子性(有序性一般不說).接下來的各種佇列主要就這兩點的實現來說.
非阻塞佇列即不使用鎖的佇列,主要使用cas操作保證原子性
concurrentlinkedqueue
concurrentlinkedqueue是無界非阻塞佇列.底層資料結構是單向鍊錶,通過volatile分別修飾兩個節點,這兩個節點分別存放鍊錶的頭結點和尾節點來實現可見性,通過cas操作保證節點入隊出隊時操作鍊錶的原子性.
poll() : 從隊頭移除乙個元素
peek():獲取頭結點元素,不移除
size() ; 獲取佇列長度
linkedblockingqueue
使用reentrantlock實現鎖機制,底層也是單向列表,也有兩個節點存放頭節點和尾節點,還有乙個count代表元素個數.
put() ; 類似offer,不過如果佇列已滿不會返回false,而是阻塞執行緒,直到佇列空閒再插入
poll:從頭部移除乙個元素,如果隊列為空返回null,該方法不阻塞
peek():獲取頭部元素但不刪除,隊列為空返回null.
take():類似poll,不過隊列為空阻塞執行緒直到佇列不為空.
方法是不是阻塞的,就是當佇列滿或空時是否阻塞執行緒.如果被阻塞的執行緒被其他執行緒呼叫了中斷方法,會丟擲interruptedexception
異常而返回.
offer和put操作成功後,會通知被take操作阻塞的執行緒,類似的,take和poll操作成功後也會通知被put操作阻塞的執行緒.
arrayblockingqueue
底層通過陣列實現的有界佇列.維持兩個下標,乙個入隊下標,乙個出隊下標.因為是陣列,所以只使用乙個獨佔鎖,也就意味著同時只有乙個執行緒進行入隊和出隊操作.
put(); 操作,向隊尾插入乙個元素,如果佇列有空閒則插入成功後直接返回true,如果佇列已滿則阻塞執行緒知道佇列有空閒並插入成功並返回true;
poll():從頭部移除乙個元素,如果隊列為空返回null;
take();從頭部移除乙個元素,如果佇列空,則阻塞執行緒.
priorityblockingqueue
priorityblockingqueue
是乙個帶優先順序的無界阻塞佇列,每次出兌都返回優先順序最高或者最低的元素,內部採用平衡二叉樹堆實現,所以直接遍歷佇列元素不保證有序,因為是帶優先順序的,所以佇列元素必須實現comparable
介面,然後設定物件的compareto
方法,值得一提的是,最大堆還是最小堆是由這個方法決定的;底層採用陣列存放元素,
poll() : 獲取佇列內部堆樹的根節點元素,如果佇列溫控,返回null,這個方法不是阻塞的,但是當一處根節點元素後,整個陣列需要調整,建立新的堆;
put(e e) : 因為是無界的, 所以就是offer
take() : 獲取佇列中根節點的元素,如果隊列為空,阻塞執行緒
size( ) : 安全的,內部加鎖;
Java併發 阻塞原理
阻塞原理 當我們請求某個已經被其他執行緒持有的物件鎖,或者呼叫某個物件的wait方法時,當前執行緒 請求者或呼叫者 會阻塞,原理大概如下 每個物件其實都有個佇列管理競爭該物件的所有執行緒物件,執行緒阻塞 直接呼叫這個物件的wait方法或者請求該物件的鎖 其實就是把物件加入到該佇列 另乙個擁有鎖的執行...
java 併發佇列 前言 一
jdk為我們提供了一系列多執行緒安全的佇列.按實現方式的不同可以分為阻塞佇列和非阻塞佇列.先來看一組類圖 阻塞佇列 非阻塞佇列 從上面的類圖可以看出,阻塞與非阻塞就在於是否實現了blockingqueue這個介面.這個是乙個阻塞佇列介面.blockingqueue增加了2個阻塞方法 以上只是介面在定...
Java併發程式設計 延時任務佇列的實現原理
優先順序佇列delayedworkqueue delayedworkqueue用來存放將要執行的任務,其資料結構為有序二叉堆。有序二叉堆的特點 所有根結點必定不大於其兩個葉子節點 任意結點的子節點的索引位置是其本身索引位置乘2後 1 任意結點的父節點的索引位置是該結點的索引位置 1後除2並向下取整 ...