隊列--queue詳解

Queue: 基本上,一個隊列就是一個先入先出(FIFO)的數據結構java

Queue接口與List、Set同一級別,都是繼承了Collection接口。LinkedList實現了Deque接 口。數組

Queue的實現安全


一、沒有實現的阻塞接口的LinkedList: 實現了java.util.Queue接口和java.util.AbstractQueue接口
  內置的不阻塞隊列: PriorityQueue 和 ConcurrentLinkedQueue
  PriorityQueue 和 ConcurrentLinkedQueue 類在 Collection Framework 中加入兩個具體集合實現。 
  PriorityQueue 類實質上維護了一個有序列表。加入到 Queue 中的元素根據它們的自然排序(經過其 java.util.Comparable 實現)或者根據傳遞給構造函數的 java.util.Comparator 實現來定位。
  ConcurrentLinkedQueue 是基於連接節點的、線程安全的隊列。併發訪問不須要同步。由於它在隊列的尾部添加元素並從頭部刪除它們,因此只要不須要知道隊列的大 小,ConcurrentLinkedQueue 對公共集合的共享訪問就能夠工做得很好。收集關於隊列大小的信息會很慢,須要遍歷隊列。數據結構


二、實現阻塞接口的:
  java.util.concurrent 中加入了 BlockingQueue 接口和五個阻塞隊列類。它實質上就是一種帶有一點扭曲的 FIFO 數據結構。不是當即從隊列中添加或者刪除元素,線程執行操做阻塞,直到有空間或者元素可用。
  五個隊列所提供的各有不一樣:併發

  •  ArrayBlockingQueue :  一個由數組支持的有界隊列。
  • LinkedBlockingQueue :  一個由連接節點支持的可選有界隊列。
  • PriorityBlockingQueue :一個由優先級堆支持的無界優先級隊列。
  • DelayQueue :           一個由優先級堆支持的、基於時間的調度隊列。
  • SynchronousQueue :     一個利用 BlockingQueue 接口的簡單彙集(rendezvous)機制。

三、主要方法:app

    add        增長一個元索                     若是隊列已滿,則拋出一個IIIegaISlabEepeplian異常
  remove     移除並返回隊列頭部的元素         若是隊列爲空,則拋出一個NoSuchElementException異常
  element    返回隊列頭部的元素               若是隊列爲空,則拋出一個NoSuchElementException異常
  offer      添加一個元素並返回true           若是隊列已滿,則返回false
  poll       移除並返問隊列頭部的元素         若是隊列爲空,則返回null
  peek       返回隊列頭部的元素               若是隊列爲空,則返回null
  put        添加一個元素                     若是隊列滿,則阻塞
  take       移除並返回隊列頭部的元素         若是隊列爲空,則阻塞
ide

四、四種隊列詳解函數

  (1)LinkedBlockingQueue的容量是沒有上限的(說的不許確,在不指定時容量爲Integer.MAX_VALUE,不要然的話在put時怎麼會受阻呢),可是也能夠選擇指定其最大容量,它是基於鏈表的隊列,此隊列按 FIFO(先進先出)排序元素。性能

  (2)ArrayBlockingQueue在構造時須要指定容量, 並能夠選擇是否須要公平性,若是公平參數被設置true,等待時間最長的線程會優先獲得處理(其實就是經過將ReentrantLock設置爲true來 達到這種公平性的:即等待時間最長的線程會先操做)。一般,公平性會使你在性能上付出代價,只有在的確很是須要的時候再使用它。它是基於數組的阻塞循環隊 列,此隊列按 FIFO(先進先出)原則對元素進行排序。ui

  (3)PriorityBlockingQueue是一個帶優先級的 隊列,而不是先進先出隊列。元素按優先級順序被移除,該隊列也沒有上限(看了一下源碼,PriorityBlockingQueue是對 PriorityQueue的再次包裝,是基於堆數據結構的,而PriorityQueue是沒有容量限制的,與ArrayList同樣,因此在優先阻塞 隊列上put時是不會受阻的。雖然此隊列邏輯上是無界的,可是因爲資源被耗盡,因此試圖執行添加操做可能會致使 OutOfMemoryError),可是若是隊列爲空,那麼取元素的操做take就會阻塞,因此它的檢索操做take是受阻的。另外,往入該隊列中的元 素要具備比較能力。

  (4)DelayQueue(基於PriorityQueue來實現的)是一個存放Delayed 元素的無界阻塞隊列,只有在延遲期滿時才能從中提取元素。該隊列的頭部是延遲期滿後保存時間最長的 Delayed 元素。若是延遲都尚未期滿,則隊列沒有頭部,而且poll將返回null。當一個元素的 getDelay(TimeUnit.NANOSECONDS) 方法返回一個小於或等於零的值時,則出現期滿,poll就以移除這個元素了。此隊列不容許使用 null 元素.

 

五、代碼例子

 

package is.data.structure.queue;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;

/**
 * @ClassName: FruitBasket
 * @Description:
 * 水果籃子
 * @Author: Coding_wxb
 */
public class FruitBasket {
    private boolean close = false;
    BlockingQueue<Fruit> basket = new LinkedBlockingDeque<>(10);
    //存放水果
    public void storeFruit(Fruit fruit) throws InterruptedException{
        basket.put(fruit);
    }
    //取出水果
    public Fruit getFruit() throws InterruptedException{
        return basket.take();
    }
    //獲取籃子中的水果數量
    public int getSize(){
        return basket.size();
    }
    //水果生產者
    class Producer implements Runnable{
        @Override
        public void run() {
            try {
                while (!close){
                    System.out.println("生產者開始生產水果:");
                    Instant start = Instant.now();
                    Fruit fruit1 = new Fruit("read","apple");
                    Fruit fruit2 = new Fruit("yellow","pear");
                    storeFruit(fruit1);
                    storeFruit(fruit2);
                    Instant end = Instant.now();
                    System.out.println("生產水果總耗時:"+Duration.between(start,end).toMillis());
                    System.out.println("生產完水果,籃子中有:"+getSize()+"個水果");
                    Thread.sleep(3000);
                }
            }catch (Throwable e){
                e.printStackTrace();
            }
        }
    }
    //水果消費者
    class Consumer implements  Runnable{

        @Override
        public void run() {
            try {
                while (!close){
                    System.out.println("消費者開始消費水果:");
                    Instant start = Instant.now();
                    Fruit fruit = getFruit();
                    System.out.println("這次消費水果爲:"+fruit.toString());
                    System.out.println("生產完水果,籃子中有:"+getSize()+"個水果");
                    Instant end = Instant.now();
                    System.out.println("消費水果總耗時:"+Duration.between(start,end).toMillis());
                    Thread.sleep(3000);
                }
            }catch (Throwable e){
                e.printStackTrace();
            }
        }
    }
    public  void test(){
        ExecutorService ex = Executors.newCachedThreadPool();
        Producer producer = new Producer();
        Consumer consumer = new Consumer();
        ex.submit(producer);
        ex.submit(consumer);
        //程序運行十秒結束
        try {
            Thread.sleep(10000);
        }catch (Throwable e){
            e.printStackTrace();
        }
        ex.shutdownNow();
    }

    public static void main(String[] args) {
        FruitBasket basket = new FruitBasket();
        basket.test();
    }
    //水果類
    class Fruit{
        private String color;
        private String name;

        public Fruit(String color, String name) {
            this.color = color;
            this.name = name;
        }

        @Override
        public String toString() {
            return "Fruit{" +
                    "color='" + color + '\'' +
                    ", name='" + name + '\'' +
                    '}';
        }
    }

}
相關文章
相關標籤/搜索