1. 程式人生 > >關於concurrent包下的阻塞佇列

關於concurrent包下的阻塞佇列

在前面幾篇文章中,我們討論了同步容器(Hashtable、Vector),也討論了併發容器(ConcurrentHashMap、CopyOnWriteArrayList),這些工具都為我們編寫多執行緒程式提供了很大的方便。今天我們來討論另外一類容器:阻塞佇列。

  在前面我們接觸的佇列都是非阻塞佇列,比如PriorityQueue、LinkedList(LinkedList是雙向連結串列,它實現了Dequeue介面)。

  使用非阻塞佇列的時候有一個很大問題就是:它不會對當前執行緒產生阻塞,那麼在面對類似消費者-生產者的模型時,就必須額外地實現同步策略以及執行緒間喚醒策略,這個實現起來就非常麻煩。但是有了阻塞佇列就不一樣了,它會對當前執行緒產生阻塞,比如一個執行緒從一個空的阻塞佇列中取元素,此時執行緒會被阻塞直到阻塞佇列中有了元素。當佇列中有元素後,被阻塞的執行緒會自動被喚醒(不需要我們編寫程式碼去喚醒)。這樣提供了極大的方便性。

  本文先講述一下java.util.concurrent包下提供主要的幾種阻塞佇列,然後分析了阻塞佇列和非阻塞佇列的中的各個方法,接著分析了阻塞佇列的實現原理,最後給出了一個實際例子和幾個使用場景。

  一.幾種主要的阻塞佇列

  二.阻塞佇列中的方法 VS 非阻塞佇列中的方法

  三.阻塞佇列的實現原理

  四.示例和使用場景

  若有不正之處請多多諒解,並歡迎批評指正。

  請尊重作者勞動成果,轉載請標明原文連結:

   http://www.cnblogs.com/dolphin0520/p/3932906.html

一.幾種主要的阻塞佇列

  自從Java 1.5之後,在java.util.concurrent包下提供了若干個阻塞佇列,主要有以下幾個:

  ArrayBlockingQueue:基於陣列實現的一個阻塞佇列,在建立ArrayBlockingQueue物件時必須制定容量大小。並且可以指定公平性與非公平性,預設情況下為非公平的,即不保證等待時間最長的佇列最優先能夠訪問佇列。

  LinkedBlockingQueue:基於連結串列實現的一個阻塞佇列,在建立LinkedBlockingQueue物件時如果不指定容量大小,則預設大小為Integer.MAX_VALUE。

  PriorityBlockingQueue:以上2種佇列都是先進先出佇列,而PriorityBlockingQueue卻不是,它會按照元素的優先順序對元素進行排序,按照優先順序順序出隊,每次出隊的元素都是優先順序最高的元素。注意,此阻塞佇列為無界阻塞佇列,即容量沒有上限(通過原始碼就可以知道,它沒有容器滿的訊號標誌),前面2種都是有界佇列。

  DelayQueue:基於PriorityQueue,一種延時阻塞佇列,DelayQueue中的元素只有當其指定的延遲時間到了,才能夠從佇列中獲取到該元素。DelayQueue也是一個無界佇列,因此往佇列中插入資料的操作(生產者)永遠不會被阻塞,而只有獲取資料的操作(消費者)才會被阻塞。

二.阻塞佇列中的方法 VS 非阻塞佇列中的方法

1.非阻塞佇列中的幾個主要方法:

  add(E e):將元素e插入到佇列末尾,如果插入成功,則返回true;如果插入失敗(即佇列已滿),則會丟擲異常;

  remove():移除隊首元素,若移除成功,則返回true;如果移除失敗(佇列為空),則會丟擲異常;

  offer(E e):將元素e插入到佇列末尾,如果插入成功,則返回true;如果插入失敗(即佇列已滿),則返回false;

  poll():移除並獲取隊首元素,若成功,則返回隊首元素;否則返回null;

  peek():獲取隊首元素,若成功,則返回隊首元素;否則返回null

  對於非阻塞佇列,一般情況下建議使用offer、poll和peek三個方法,不建議使用add和remove方法。因為使用offer、poll和peek三個方法可以通過返回值判斷操作成功與否,而使用add和remove方法卻不能達到這樣的效果。注意,非阻塞佇列中的方法都沒有進行同步措施。

2.阻塞佇列中的幾個主要方法:

  阻塞佇列包括了非阻塞佇列中的大部分方法,上面列舉的5個方法在阻塞佇列中都存在,但是要注意這5個方法在阻塞佇列中都進行了同步措施。除此之外,阻塞佇列提供了另外4個非常有用的方法:

  put(E e)

  take()

  offer(E e,long timeout, TimeUnit unit)

  poll(long timeout, TimeUnit unit)

  put方法用來向隊尾存入元素,如果佇列滿,則等待;

  take方法用來從隊首取元素,如果佇列為空,則等待;

  offer方法用來向隊尾存入元素,如果佇列滿,則等待一定的時間,當時間期限達到時,如果還沒有插入成功,則返回false;否則返回true;

  poll方法用來從隊首取元素,如果佇列空,則等待一定的時間,當時間期限達到時,如果取到,則返回null;否則返回取得的元素;

三.阻塞佇列的實現原理

  前面談到了非阻塞佇列和阻塞佇列中常用的方法,下面來探討阻塞佇列的實現原理,本文以ArrayBlockingQueue為例,其他阻塞佇列實現原理可能和ArrayBlockingQueue有一些差別,但是大體思路應該類似,有興趣的朋友可自行檢視其他阻塞佇列的實現原始碼。

  首先看一下ArrayBlockingQueue類中的幾個成員變數:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public class ArrayBlockingQueue<E> extends AbstractQueue<E> implements BlockingQueue<E>, java.io.Serializable { private static final long serialVersionUID = -817911632652898426L; /** The queued items  */ private final E[] items; /** items index for next take, poll or remove */ private int takeIndex; /** items index for next put, offer, or add. */ private int putIndex; /** Number of items in the queue */ private int count; /* * Concurrency control uses the classic two-condition algorithm * found in any textbook. */ /** Main lock guarding all access */ private final ReentrantLock lock; /** Condition for waiting takes */ private final Condition notEmpty;

相關推薦

關於concurrent阻塞佇列

在前面幾篇文章中,我們討論了同步容器(Hashtable、Vector),也討論了併發容器(ConcurrentHashMap、CopyOnWriteArrayList),這些工具都為我們編寫多執行緒程式提供了很大的方便。今天我們來討論另外一類容器:阻塞佇列。

Java基礎知識-java.util.concurrent常見類的使用

finall iss con value 通信 out 否則 app ted 一,Condition 一個場景,兩個線程數數,同時啟動兩個線程,線程A數1、2、3,然後線程B數4、5、6,最後線程A數7、8、9,程序結束,這涉及到線程之間的通信。 public class

併發阻塞佇列ConcurrentLinkedQueue

jdk1.7.0_79    佇列是一種非常常用的資料結構,一進一出,先進先出。    在Java併發包中提供了兩種型別的佇列,非阻塞佇列與阻塞佇列,當然它們都是執行緒安全的,無需擔心在多執行緒併發環境所帶來的不可預知的問題。為什麼會有非阻塞和阻塞之分呢?這裡的非

java.util.concurrent同步輔助工具類CountDownLatch

        CountDownLatch作為一個輔助工具類,它允許一個或多個執行緒等待一系列指定操作的完成。CountDownLatch以一個給定值進行初始化,通過CountDownLatch cd

java.util.concurrent的類 (轉)

文章整理來源:http://www.cnblogs.com/aurawing/articles/1887056.html 一 ,背景: 在JDK1.5之前,Java中要進行業務併發時,通常需要有程式設計師獨立完成程式碼實現,當然也有一些開源的框架提供了這些功能,但是這些依然沒有JDK自帶的功

JAVA中常用的高階集合類總結(包含Concurrent的併發集合類)

MAP WeakHashMap 和普通的HashMap相比,當除了自身有對key的引用外,此key沒有其他引用那麼此map會自動丟棄此值,從而解決HashMap物件中key-value資源無法釋放,導

執行緒併發執行緒安全介紹及java.util.concurrent類介紹

執行緒Thread,在Java開發中多執行緒是必不可少的,但是真正能用好的並不多! 首先開啟一個執行緒三種方式  ①new Thread(Runnable).start()  ②thread.star

java.util.concurrent的幾個常用類

1.Callable<V> Callable<V>與Runnable類似,理解Callable<V>可以從比較其與Runnable的區別開始: 1)從使用上:實現的Callable<V>的類需要實現call()方法,此方

【一】關於java.util.concurrent的併發類(atomic)

併發類包除了java.util.concurrent之外,還有java.util.concurrent.atomic和java.util.concurrent.lock.java.util.concurrent中主要是一些關於集合框架的併發實現,例如ConcurrentHas

掌握併發佇列

說到佇列尤其是阻塞佇列,不得不說jdk的併發包(Java.util.concurrent)中的相關資料結構,今天我們就來對java(JDK1.7)中的佇列做一個總結。 1、Queue 佇列介面,定義了佇列基本的介面方法 前兩個方法是往佇列塞資料,在佇列空間不足的情況

ConCurrent工具類-CountDownLatch

CountDownLatch是JAVA提供在java.util.concurrent包下的一個輔助類,可以把它看成是一個計數器,其內部維護著一個count計數,只不過對這個計數器的操作都是原子操作,同時只能有一個執行緒去操作這個計數器,CountDownLatc

Java併發阻塞佇列

本文簡要介紹一下什麼是阻塞佇列,Java併發包給我們提供的阻塞佇列有哪些,以及怎麼去簡單使用 阻塞佇列 BlockingQueue 1. 簡單概念  阻塞佇列(BlockingQueue)是一個支援兩個附加操作的佇列:支援阻塞的插入和移除: 支援阻塞

死磕java concurrent系列(三)基於ReentrantLock理解AQS的條件佇列

基於Codition分析AQS的條件佇列 前言 上一篇我們講了AQS中的同步佇列佇列,現在我們研究一下條件佇列。 在java中最常見的加鎖方式就是synchorinzed和Reentrantlock,我們都說Reentrantlock比synchorinzed更加靈活,其實就靈活在Reentrantlock中

jdk提供的阻塞佇列BlockingQueue的五個實現簡單操作以及介紹

package cn.yarne.com.base.test; import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.Vector;

死磕java concurrent系列(五)基於AQS的條件佇列把LinkedBlockingQueue“扒光”

LinkedBlockingQueue的基礎 LinkedBlockingQueue是一個基於連結串列的阻塞佇列,實際使用上與ArrayBlockingQueue完全一樣,我們只需要把之前烤雞的例子中的Queue物件替換一下即可。如果對於ArrayBlockingQueue不熟悉,可以去看看https://

併發程式設計-concurrent指南-阻塞佇列BlockingQueue

阻塞佇列BlockingQueue,java.util.concurrent下的BlockingQueue介面表示一個執行緒放入和提取例項的佇列。 適用場景: BlockingQueue通常用於一個執行緒生產物件,而另一個執行緒消費物件的場景。 一個執行緒往裡面放,另一個執行緒從裡面取的一個Bloc

併發程式設計-concurrent指南-阻塞佇列-優先順序的阻塞佇列PriorityBlockingQueue

PriorityBlockingQueue是一個支援優先順序的無界阻塞佇列。 它使用了和類 java.util.PriorityQueue 一樣的排序規則。你無法向這個佇列中插入 null 值。 所有插入到 PriorityBlockingQueue 的元素必須實現 java.lang.Comparabl

Java 使用阻塞佇列 BlockingQueue 多執行緒搜尋目錄及子目錄包含關鍵字所有檔案

Java 使用阻塞佇列 BlockingQueue 多執行緒在一個目錄及它的所以子目錄下搜尋所有檔案,打印出包含關鍵字的行 阻塞佇列( blocking queue ) 生產者執行緒向佇列插人元素, 消費者執行緒則取出它們。使用佇列,可以安全地從一個執行緒向另一個執行緒傳遞資料。

java concurrent自帶執行緒池和佇列詳細講解

Java執行緒池使用說明一簡介執行緒的使用在java中佔有極其重要的地位,在jdk1.4極其之前的jdk版本中,關於執行緒池的使用是極其簡陋的。在jdk1.5之後這一情況有了很大的改觀。Jdk1.5之後加入了java.util.concurrent包,這個包中主要介紹java

Java併發原始碼學習系列:阻塞佇列BlockingQueue及實現原理分析

[toc] 系列傳送門: - [Java併發包原始碼學習系列:AbstractQueuedSynchronizer](https://blog.csdn.net/Sky_QiaoBa_Sum/article/details/112254373) - [Java併發包原始碼學習系列:CLH同步佇列及同步資源