您好,登錄后才能下訂單哦!
這篇文章主要介紹了Java并發隊列BlockingQueue怎么用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇Java并發隊列BlockingQueue怎么用文章都會有所收獲,下面我們一起來看看吧。
首先,最基本的來說, BlockingQueue 是一個先進先出的隊列(Queue),為什么說是阻塞(Blocking)的呢?是因為 BlockingQueue 支持當獲取隊列元素但是隊列為空時,會阻塞等待隊列中有元素再返回;也支持添加元素時,如果隊列已滿,那么等到隊列可以放入新元素時再放入。
BlockingQueue 是一個接口,繼承自 Queue,所以其實現類也可以作為 Queue 的實現來使用,而 Queue 又繼承自 Collection 接口。
BlockingQueue 對插入操作、移除操作、獲取元素操作提供了四種不同的方法用于不同的場景中使用:1、拋出異常;2、返回特殊值(null 或 true/false,取決于具體的操作);3、阻塞等待此操作,直到這個操作成功;4、阻塞等待此操作,直到成功或者超時指定時間。總結如下:
Throws exception | Special value | Blocks | Times out | |
---|---|---|---|---|
Insert | add(e) | offer(e) | put(e) | offer(e, time, unit) |
Remove | remove() | poll() | take() | poll(time, unit) |
Examine | element() | peek() | not applicable | not applicable |
BlockingQueue 的各個實現都遵循了這些規則,當然我們也不用死記這個表格,知道有這么回事,然后寫代碼的時候根據自己的需要去看方法的注釋來選取合適的方法即可。
對于 BlockingQueue,我們的關注點應該在 put(e) 和 take() 這兩個方法,因為這兩個方法是帶阻塞的。
BlockingQueue 不接受 null 值的插入,相應的方法在碰到 null 的插入時會拋出 NullPointerException 異常。null 值在這里通常用于作為特殊值返回(表格中的第三列),代表 poll 失敗。所以,如果允許插入 null 值的話,那獲取的時候,就不能很好地用 null 來判斷到底是代表失敗,還是獲取的值就是 null 值。
一個 BlockingQueue 可能是有界的,如果在插入的時候,發現隊列滿了,那么 put 操作將會阻塞。通常,在這里我們說的無界隊列也不是說真正的無界,而是它的容量是 Integer.MAX_VALUE(21億多)。
BlockingQueue 是設計用來實現生產者-消費者隊列的,當然,你也可以將它當做普通的 Collection 來用,前面說了,它實現了 java.util.Collection 接口。例如,我們可以用 remove(x) 來刪除任意一個元素,但是,這類操作通常并不高效,所以盡量只在少數的場合使用,比如一條消息已經入隊,但是需要做取消操作的時候。
BlockingQueue 的實現都是線程安全的,但是批量的集合操作如 addAll
, containsAll
, retainAll
和 removeAll
不一定是原子操作。如 addAll(c) 有可能在添加了一些元素后中途拋出異常,此時 BlockingQueue 中已經添加了部分元素,這個是允許的,取決于具體的實現。
BlockingQueue 不支持 close 或 shutdown 等關閉操作,因為開發者可能希望不會有新的元素添加進去,此特性取決于具體的實現,不做強制約束。
最后,BlockingQueue 在生產者-消費者的場景中,是支持多消費者和多生產者的,說的其實就是線程安全問題。
相信上面說的每一句都很清楚了,BlockingQueue 是一個比較簡單的線程安全容器,下面我會分析其具體的在 JDK 中的實現,這里又到了 Doug Lea 表演時間了。
ArrayBlockingQueue 是 BlockingQueue 接口的有界隊列實現類,底層采用數組來實現。
其并發控制采用可重入鎖來控制,不管是插入操作還是讀取操作,都需要獲取到鎖才能進行操作。
ArrayBlockingQueue 共有以下幾個屬性:
// 用于存放元素的數組 final Object[] items; // 下一次讀取操作的位置 int takeIndex; // 下一次寫入操作的位置 int putIndex; // 隊列中的元素數量 int count; // 以下幾個就是控制并發用的同步器 final ReentrantLock lock; private final Condition notEmpty; private final Condition notFull;
我們用個示意圖來描述其同步機制:
好了, PriorityBlockingQueue 我們也說完了。
關于“Java并發隊列BlockingQueue怎么用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“Java并發隊列BlockingQueue怎么用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。