java隊列——queue詳細分析

Queue: 基本上,一個隊列就是一個先入先出(FIFO)的數(shù)據(jù)結(jié)構(gòu)

Queue接口與List瓢湃、Set同一級別村怪,都是繼承了Collection接口剩彬。LinkedList實現(xiàn)了Deque接 口。

Queue的實現(xiàn)

1、沒有實現(xiàn)的阻塞接口的LinkedList: 實現(xiàn)了java.util.Queue接口和java.util.AbstractQueue接口
  內(nèi)置的不阻塞隊列: PriorityQueue 和 ConcurrentLinkedQueue
  PriorityQueue 和 ConcurrentLinkedQueue 類在 Collection Framework 中加入兩個具體集合實現(xiàn)否淤。
  PriorityQueue 類實質(zhì)上維護了一個有序列表悄但。加入到 Queue 中的元素根據(jù)它們的天然排序(通過其 java.util.Comparable 實現(xiàn))或者根據(jù)傳遞給構(gòu)造函數(shù)的 java.util.Comparator 實現(xiàn)來定位。
  ConcurrentLinkedQueue 是基于鏈接節(jié)點的石抡、線程安全的隊列檐嚣。并發(fā)訪問不需要同步。因為它在隊列的尾部添加元素并從頭部刪除它們啰扛,所以只要不需要知道隊列的大 小嚎京,       ConcurrentLinkedQueue 對公共集合的共享訪問就可以工作得很好。收集關(guān)于隊列大小的信息會很慢隐解,需要遍歷隊列鞍帝。

2)實現(xiàn)阻塞接口的:
  java.util.concurrent 中加入了 BlockingQueue 接口和五個阻塞隊列類。它實質(zhì)上就是一種帶有一點扭曲的 FIFO 數(shù)據(jù)結(jié)構(gòu)厢漩。不是立即從隊列中添加或者刪除元素膜眠,線程執(zhí)行操作阻塞,直到有空間或者元素可用溜嗜。
五個隊列所提供的各有不同:
  * ArrayBlockingQueue :一個由數(shù)組支持的有界隊列宵膨。
  * LinkedBlockingQueue :一個由鏈接節(jié)點支持的可選有界隊列。
  * PriorityBlockingQueue :一個由優(yōu)先級堆支持的無界優(yōu)先級隊列炸宵。
  * DelayQueue :一個由優(yōu)先級堆支持的辟躏、基于時間的調(diào)度隊列。
  * SynchronousQueue :一個利用 BlockingQueue 接口的簡單聚集(rendezvous)機制土全。

image.png

下表顯示了jdk1.5中的阻塞隊列的操作:

  add 增加一個元索 如果隊列已滿捎琐,則拋出一個IIIegaISlabEepeplian異常
  remove 移除并返回隊列頭部的元素 如果隊列為空,則拋出一個NoSuchElementException異常
**  element **返回隊列頭部的元素 如果隊列為空裹匙,則拋出一個NoSuchElementException異常
  offer 添加一個元素并返回true 如果隊列已滿瑞凑,則返回false
  poll 移除并返問隊列頭部的元素 如果隊列為空,則返回null
  peek 返回隊列頭部的元素 如果隊列為空概页,則返回null
  put 添加一個元素 如果隊列滿籽御,則阻塞
  take 移除并返回隊列頭部的元素 如果隊列為空,則阻塞

**remove惰匙、element技掏、offer 、poll项鬼、peek 其實是屬于Queue接口哑梳。 **

阻塞隊列的操作可以根據(jù)它們的響應(yīng)方式分為以下三類:aad、removee和element操作在你試圖為一個已滿的隊列增加元素或從空隊列取得元素時 拋出異常绘盟。當(dāng)然鸠真,在多線程程序中悯仙,隊列在任何時間都可能變成滿的或空的,所以你可能想使用offer弧哎、poll雁比、peek方法。這些方法在無法完成任務(wù)時 只是給出一個出錯示而不會拋出異常撤嫩。

注意:poll和peek方法出錯進返回null偎捎。因此,向隊列中插入null值是不合法的

最后序攘,我們有阻塞操作put和take茴她。put方法在隊列滿時阻塞,take方法在隊列空時阻塞程奠。

LinkedBlockingQueue的容量是沒有上限的(說的不準(zhǔn)確丈牢,在不指定時容量為Integer.MAX_VALUE,不要然的話在put時怎么會受阻呢)瞄沙,但是也可以選擇指定其最大容量己沛,它是基于鏈表的隊列,此隊列按 FIFO(先進先出)排序元素距境。

ArrayBlockingQueue在構(gòu)造時需要指定容量申尼, 并可以選擇是否需要公平性,如果公平參數(shù)被設(shè)置true垫桂,等待時間最長的線程會優(yōu)先得到處理(其實就是通過將ReentrantLock設(shè)置為true來 達到這種公平性的:即等待時間最長的線程會先操作)师幕。通常,公平性會使你在性能上付出代價诬滩,只有在的確非常需要的時候再使用它霹粥。它是基于數(shù)組的阻塞循環(huán)隊 列,此隊列按 FIFO(先進先出)原則對元素進行排序疼鸟。

PriorityBlockingQueue是一個帶優(yōu)先級的 隊列后控,而不是先進先出隊列。元素按優(yōu)先級順序被移除空镜,該隊列也沒有上限(看了一下源碼忆蚀,PriorityBlockingQueue是對 PriorityQueue的再次包裝,是基于堆數(shù)據(jù)結(jié)構(gòu)的姑裂,而PriorityQueue是沒有容量限制的,與ArrayList一樣男旗,所以在優(yōu)先阻塞 隊列上put時是不會受阻的舶斧。雖然此隊列邏輯上是無界的,但是由于資源被耗盡察皇,所以試圖執(zhí)行添加操作可能會導(dǎo)致 OutOfMemoryError)茴厉,但是如果隊列為空泽台,那么取元素的操作take就會阻塞,所以它的檢索操作take是受阻的矾缓。另外怀酷,往入該隊列中的元 素要具有比較能力。

DelayQueue(基于PriorityQueue來實現(xiàn)的)是一個存放Delayed 元素的無界阻塞隊列嗜闻,只有在延遲期滿時才能從中提取元素蜕依。該隊列的頭部是延遲期滿后保存時間最長的 Delayed 元素。如果延遲都還沒有期滿琉雳,則隊列沒有頭部样眠,并且poll將返回null。當(dāng)一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小于或等于零的值時翠肘,則出現(xiàn)期滿檐束,poll就以移除這個元素了。此隊列不允許使用 null 元素束倍。

image.png
package com.yao;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class BlockingQueueTest {
 /**
 定義裝蘋果的籃子
  */
 public static class Basket{
  // 籃子被丧,能夠容納3個蘋果
  BlockingQueue<String> basket = new ArrayBlockingQueue<String>(3);

  // 生產(chǎn)蘋果,放入籃子
  public void produce() throws InterruptedException{
   // put方法放入一個蘋果绪妹,若basket滿了甥桂,等到basket有位置
   basket.put("An apple");
  }
  // 消費蘋果,從籃子中取走
  public String consume() throws InterruptedException{
   // get方法取出一個蘋果喂急,若basket為空格嘁,等到basket有蘋果為止
   String apple = basket.take();
   return apple;
  }

  public int getAppleNumber(){
   return basket.size();
  }

 }
 // 測試方法
 public static void testBasket() {
  // 建立一個裝蘋果的籃子
  final Basket basket = new Basket();
  // 定義蘋果生產(chǎn)者
  class Producer implements Runnable {
   public void run() {
    try {
     while (true) {
      // 生產(chǎn)蘋果
      System.out.println("生產(chǎn)者準(zhǔn)備生產(chǎn)蘋果:" 
        + System.currentTimeMillis());
      basket.produce();
      System.out.println("生產(chǎn)者生產(chǎn)蘋果完畢:" 
        + System.currentTimeMillis());
      System.out.println("生產(chǎn)完后有蘋果:"+basket.getAppleNumber()+"個");
      // 休眠300ms
      Thread.sleep(300);
     }
    } catch (InterruptedException ex) {
    }
   }
  }
  // 定義蘋果消費者
  class Consumer implements Runnable {
   public void run() {
    try {
     while (true) {
      // 消費蘋果
      System.out.println("消費者準(zhǔn)備消費蘋果:" 
        + System.currentTimeMillis());
      basket.consume();
      System.out.println("消費者消費蘋果完畢:" 
        + System.currentTimeMillis());
      System.out.println("消費完后有蘋果:"+basket.getAppleNumber()+"個");
      // 休眠1000ms
      Thread.sleep(1000);
     }
    } catch (InterruptedException ex) {
    }
   }
  }

  ExecutorService service = Executors.newCachedThreadPool();
  Producer producer = new Producer();
  Consumer consumer = new Consumer();
  service.submit(producer);
  service.submit(consumer);
  // 程序運行10s后,所有任務(wù)停止
  try {
   Thread.sleep(10000);
  } catch (InterruptedException e) {
  }
  service.shutdownNow();
 }
 public static void main(String[] args) {
  BlockingQueueTest.testBasket();
 }
}

非阻塞隊列:ConcurrentLinkedQueue(無界線程安全)廊移,采用CAS機制(compareAndSwapObject原子操作)糕簿。
阻塞隊列:ArrayBlockingQueue(有界)、LinkedBlockingQueue(無界)狡孔、DelayQueue懂诗、PriorityBlockingQueue,采用鎖機制苗膝;使用 ReentrantLock 鎖殃恒。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市辱揭,隨后出現(xiàn)的幾起案子离唐,更是在濱河造成了極大的恐慌,老刑警劉巖问窃,帶你破解...
    沈念sama閱讀 223,002評論 6 519
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件亥鬓,死亡現(xiàn)場離奇詭異,居然都是意外死亡域庇,警方通過查閱死者的電腦和手機嵌戈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,357評論 3 400
  • 文/潘曉璐 我一進店門覆积,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熟呛,你說我怎么就攤上這事宽档。” “怎么了庵朝?”我有些...
    開封第一講書人閱讀 169,787評論 0 365
  • 文/不壞的土叔 我叫張陵吗冤,是天一觀的道長。 經(jīng)常有香客問我偿短,道長欣孤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,237評論 1 300
  • 正文 為了忘掉前任昔逗,我火速辦了婚禮降传,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘勾怒。我一直安慰自己婆排,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 69,237評論 6 398
  • 文/花漫 我一把揭開白布笔链。 她就那樣靜靜地躺著段只,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鉴扫。 梳的紋絲不亂的頭發(fā)上赞枕,一...
    開封第一講書人閱讀 52,821評論 1 314
  • 那天,我揣著相機與錄音坪创,去河邊找鬼炕婶。 笑死,一個胖子當(dāng)著我的面吹牛莱预,可吹牛的內(nèi)容都是我干的柠掂。 我是一名探鬼主播,決...
    沈念sama閱讀 41,236評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼依沮,長吁一口氣:“原來是場噩夢啊……” “哼涯贞!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起危喉,我...
    開封第一講書人閱讀 40,196評論 0 277
  • 序言:老撾萬榮一對情侶失蹤宋渔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后辜限,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傻谁,經(jīng)...
    沈念sama閱讀 46,716評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,794評論 3 343
  • 正文 我和宋清朗相戀三年列粪,在試婚紗的時候發(fā)現(xiàn)自己被綠了审磁。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,928評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡岂座,死狀恐怖态蒂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情费什,我是刑警寧澤钾恢,帶...
    沈念sama閱讀 36,583評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站鸳址,受9級特大地震影響瘩蚪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜稿黍,卻給世界環(huán)境...
    茶點故事閱讀 42,264評論 3 336
  • 文/蒙蒙 一疹瘦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巡球,春花似錦言沐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,755評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至矿筝,卻和暖如春起便,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窖维。 一陣腳步聲響...
    開封第一講書人閱讀 33,869評論 1 274
  • 我被黑心中介騙來泰國打工榆综, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陈辱。 一個月前我還...
    沈念sama閱讀 49,378評論 3 379
  • 正文 我出身青樓奖年,卻偏偏與公主長得像,于是被迫代替她去往敵國和親沛贪。 傳聞我的和親對象是個殘疾皇子陋守,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,937評論 2 361