Java中 BlockingQueue(阻塞佇列)的使用
引言
Queue介面與List、Set同一級別,都是繼承了Collection介面。LinkedList實現了Queue接 口。Queue介面窄化了對LinkedList的方法的訪問許可權(即在方法中的引數型別如果是Queue時,就完全只能訪問Queue介面所定義的方法 了,而不能直接訪問 LinkedList的非Queue的方法),以使得只有恰當的方法才可以使用。BlockingQueue 繼承了Queue介面。LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue、DelayQueue實現了BlockingQueue 介面。
佇列是一種資料結構,它有兩個基本操作:在佇列尾部加人一個元素,和從佇列頭部移除一個元素就是說,佇列以一種先進先出的方式管理資料,如果你試圖向一個已經滿了的阻塞佇列中新增一個元素或者是從一個空的阻塞佇列中移除一個元素,將導致執行緒阻塞。在多執行緒進行合作時,阻塞佇列是很有用的工具。工作者執行緒可以定期地把中間結果存到阻塞佇列中而其他工作者執行緒把中間結果取出並在將來修改它們。佇列會自動平衡負載。如果第一個執行緒集執行得比第二個慢,則第二個執行緒集在等待結果時就會阻塞。如果第一個執行緒集執行得快,那麼它將等待第二個執行緒集趕上來。下表顯示了 jdk1.5 中阻塞佇列的操作:
方法名 | 說明 | 注意 |
---|---|---|
add | 增加一個元索 | 如果佇列已滿,則丟擲一個IIIegaISlabEepeplian異常 |
remove | 移除並返回佇列頭部的元素 | 如果佇列為空,則丟擲一個NoSuchElementException異常 |
element | 返回佇列頭部的元素 | 如果佇列為空,則丟擲一個NoSuchElementException異常 |
offer | 新增一個元素並返回true | 如果佇列已滿,則返回false |
poll | 移除並返問佇列頭部的元素 | 如果佇列為空,則返回null |
peek | 返回佇列頭部的元素 | 如果佇列為空,則返回null |
put | 新增一個元素 | 如果佇列滿,則阻塞 |
take | 移除並返回佇列頭部的元素 | 如果佇列為空,則阻塞 |
注:remove、element、offer 、poll、peek 其實是屬於Queue介面。
阻塞佇列的操作可以根據它們的響應方式分為以下三類:aad、removee和element操作在你試圖為一個已滿的佇列增加元素或從空佇列取得元素時丟擲異常。當然,在多執行緒程式中,佇列在任何時間都可能變成滿的或空的,所以你可能想使用offer、poll、peek方法。這些方法在無法完成任務時 只是給出一個出錯示而不會丟擲異常。
注意:poll和peek方法出錯進返回null。因此,向佇列中插入null值是不合法的。
還有帶超時的offer和poll方法變種,例如,下面的呼叫:
boolean success = q.offer(x,100,TimeUnit.MILLISECONDS);
嘗試在100毫秒內向佇列尾部插入一個元素。如果成功,立即返回true;否則,當到達超時進,返回false。同樣地,呼叫:
Object head = q.poll(100, TimeUnit.MILLISECONDS);
如果在100毫秒內成功地移除了佇列頭元素,則立即返回頭元素;否則在到達超時時,返回null。
最後,我們有阻塞操作put和take。put方法在佇列滿時阻塞,take方法在佇列空時阻塞。
正文
java.ulil.concurrent包提供了阻塞佇列的4個實現類:LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue、DelayQueue
LinkedBlockingQueue
LinkedBlockingQueue的容量在不指定的情況下為 Integer.MAX_VALUE,但是也可以指定其最大容量,其中主要用到 put 和 take 方法,它是基於連結串列的佇列,此佇列按 FIFO (先進先出)排序元素,是執行緒安全的。
ArrayBlockingQueue
ArrayBlockingQueue在構造時需要指定容量,並可以選擇是否需要公平性,如果公平引數被設定為 true,等待時間最長的執行緒會優先得到處理(其實就是通過將 ReentrantLock 設定為 true 來達到這種公平性:即等待時間最長的執行緒會先操作)。通常,公平性會使你在效能上付出代價,只有在的確非常需要的時候再使用它。它是基於陣列的阻塞迴圈佇列,此佇列按 FIFO(先進先出)原則對元素進行排序。
PriorityBlockingQueue
PriorityBlockingQueue是一個帶優先順序的 佇列,而不是先進先出佇列。元素按優先順序順序被移除,該佇列也沒有上限(看了一下原始碼,PriorityBlockingQueue是對 PriorityQueue的再次包裝,是基於堆資料結構的,而PriorityQueue是沒有容量限制的,與ArrayList一樣,所以在優先阻塞 佇列上put時是不會受阻的。雖然此佇列邏輯上是無界的,但是由於資源被耗盡,所以試圖執行新增操作可能會導致 OutOfMemoryError),但是如果佇列為空,那麼取元素的操作take就會阻塞,所以它的檢索操作take是受阻的。另外,往入該佇列中的元 素要具有比較能力。
DelayQueue
DelayQueue(基於PriorityQueue來實現的)是一個存放Delayed 元素的無界阻塞佇列,只有在延遲期滿時才能從中提取元素。該佇列的頭部是延遲期滿後儲存時間最長的 Delayed 元素。如果延遲都還沒有期滿,則佇列沒有頭部,並且poll將返回null。當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小於或等於零的值時,則出現期滿,poll就以移除這個元素了。此佇列不允許使用 null 元素。
相關推薦
Java中 BlockingQueue(阻塞佇列)的使用
引言 Queue介面與List、Set同一級別,都是繼承了Collection介面。LinkedList實現了Queue接 口。Queue介面窄化了對LinkedList的方法的訪問許可權(即在方法中的引數型別如果是Queue時,就完全只能訪問Queue介面所
Java併發(十八):阻塞佇列BlockingQueue BlockingQueue(阻塞佇列)詳解 二叉堆(一)之 圖文解析 和 C語言的實現 多執行緒程式設計:阻塞、併發佇列的使用總結 Java併發程式設計:阻塞佇列 java阻塞佇列 BlockingQueue(阻塞佇列)詳解
阻塞佇列(BlockingQueue)是一個支援兩個附加操作的佇列。 這兩個附加的操作是:在佇列為空時,獲取元素的執行緒會等待佇列變為非空。當佇列滿時,儲存元素的執行緒會等待佇列可用。 阻塞佇列常用於生產者和消費者的場景,生產者是往佇列裡新增元素的執行緒,消費者是從佇列裡拿元素的執行緒。阻塞佇列就是生產者
【轉載】BlockingQueue(阻塞佇列)詳解
注意:該隨筆內容完全引自http://wsmajunfeng.iteye.com/blog/1629354,寫的很好,非常感謝,複製過來算是個積累,怕以後找不到。 一. 前言 在新增的Concurrent包中,BlockingQueue很好的解決了多執行緒中,如何高效安全“傳輸”資
BlockingQueue(阻塞佇列)詳解
注意:該隨筆內容完全引自http://wsmajunfeng.iteye.com/blog/1629354,寫的很好,非常感謝,複製過來算是個積累,怕以後找不到。 一. 前言 在新增的Concurrent包中,BlockingQueue很好的解決了多執行緒中,如何高效安全“傳輸”資料的問題。通過這些高
BlockingQueue(阻塞佇列)詳解(一個生產者消費者的例項)
注意:該隨筆內容完全引自http://wsmajunfeng.iteye.com/blog/1629354,寫的很好,非常感謝,複製過來算是個積累,怕以後找不到。一. 前言 在新增的Concurrent包中,BlockingQueue很好的解決了多執行緒中,如何高效安全“傳
生產者和消費者之BlockingQueue(阻塞佇列)詳解
注意:該隨筆內容完全引自http://wsmajunfeng.iteye.com/blog/1629354,寫的很好,非常感謝,複製過來算是個積累,怕以後找不到。 一. 前言 在新增的Concurrent包中,BlockingQueue很好的解決了多執行緒中,如何
java中模擬一個阻塞佇列(多執行緒)
模擬一個阻塞佇列,當這個佇列中滿了的話,再往裡新增元素則會阻塞在那裡,直到有元素取出的時候才能往裡加,取元素的時候,當佇列是空的時候則會阻塞在那裡,一直到有元素新增為止 import java.util.LinkedList; import java.util
java中克隆(淺拷貝)的簡單使用程式碼
java中克隆的使用 1) 在被克隆類中,要提供實現克隆的介面: class Cat implements Cloneable{ } 2) 在被克隆的類中重寫clone方法,使其public化 class Cat implements Cloneable{
中位數 (優先佇列)
中位數 這種題型比較常見,所以總結下來為妙。 一般暴力的方法是找到排一個序,然後輸出中間點。 然後正解的方法是優先佇列。 解法 一個大根堆一個小根堆,用於儲存中位數左邊的數和中位數右邊的數。 然後每一次插入某個數的時候,可以插入到中間,然後判斷左右兩個堆的大小,保持均等即可。 #include &l
關於執行緒同步的問題(阻塞佇列)
package com.bootdo.wang; import java.util.Random; import java.util.concurrent.LinkedBlockingQueue; /*** * 執行緒同步: * 1.方法同步 * 2.程式碼塊同步 * 3.使
Java中建立(例項化)物件的五種方式
Java中建立(例項化)物件的五種方式1、用new語句建立物件,這是最常見的建立物件的方法。 2、通過工廠方法返回物件,如:String str = String.valueOf(23); 3、運用反射手段,呼叫java.lang.Class或者java.lang.r
JAVA中常見的阻塞佇列詳解
![](https://img2020.cnblogs.com/other/2024393/202011/2024393-20201116085210744-2073386236.jpg) * 在之前的執行緒池的介紹中我們看到了很多阻塞佇列,這篇文章我們主要來說說阻塞佇列的事。 * 阻塞佇列也就是 `Blo
Java併發(10)- 簡單聊聊JDK中的七大阻塞佇列
引言 JDK中除了上文提到的各種併發容器,還提供了豐富的阻塞佇列。阻塞佇列統一實現了BlockingQueue介面,BlockingQueue介面在java.util包Queue介面的基礎上提供了put(e)以及take()兩個阻塞方法。他的主要使用場景就是多執行緒下的生產者消費者模式,生產者執行緒通過put
Java併發包:阻塞佇列(BlockingQueue)
BlockingQueue 在java.util.concurrent包中的 BlockingQueue介面類是一種執行緒安全的佇列。這篇文章我們將展示如何使用BlockingQueue。 這篇文章不討論BlockQueue的實現。如果你對此感興趣,有一片理論
Java多執行緒---阻塞佇列詳解(舉例說明)
一. 前言 在新增的Concurrent包中,BlockingQueue很好的解決了多執行緒中,如何高效安全“傳輸”資料的問題。通過這些高效並且執行緒安全的佇列類,為我們快速搭建高質量的多執行緒程式帶來極大的便利。本文詳細介紹了BlockingQueue家庭中的所有成員
java中(優先佇列)PriorityQueue的使用
import java.util.*; public class test1 { public static void PrintPr(Queue<?> queue){ while(queue.peek()!=null){ System.ou
Java併發框架——AQS阻塞佇列管理(一)——自旋鎖
我們知道一個執行緒在嘗試獲取鎖失敗後將被阻塞並加入等待佇列中,它是一個怎樣的佇列?又是如何管理此佇列?這節聊聊CHL Node FIFO佇列。 在談到CHL Node FIFO佇列之前,我們先分析這種佇列的幾個要素。首先要了解的是自旋鎖,所謂自旋鎖即是某一執行緒去嘗試獲取某個
java中執行緒阻塞之sleep、suspend、join、wait、resume、notify方法解析(一)
java執行緒的5狀態包括create、runnable、running、blocked、dead。 create是指用new執行緒被建立,但是還沒有準備好各種資源。 runnable是指使用start啟動執行緒,這時候系統會為執行緒分配除cpu以外的所有需要的資源。 ru
Java同步佇列(非阻塞佇列與阻塞佇列)——java併發容器
在併發程式設計中,有時候需要使用執行緒安全的佇列。如果要實現一個執行緒安全的佇列有兩種方式:一種是使用阻塞演算法,另一種是使用非阻塞演算法。 使用阻塞演算法的佇列可以用一個鎖(入隊和出隊用同一把鎖)或兩個鎖(入隊和出隊用不同的鎖)等方式來實現。 非阻塞的實現方式則可以使用
Java設計模式—生產者消費者模式(阻塞佇列實現)
生產者消費者模式是併發、多執行緒程式設計中經典的設計模式,生產者和消費者通過分離的執行工作解耦,簡化了開發模式,生產者和消費者可以以不同的速度生產和消費資料。這篇文章我們來看看什麼是生產者消費者模式,這個問題也是多執行緒面試題中經常被提及的。如何使用阻塞佇列(Blocki