七大阻塞隊列的使用

1 Queue<E>接口

public interface Queue<E> extends Collection<E> {
    // 插入指定元素
    // 插入成功返回true吁恍;如果隊列沒有可用空間劣砍,拋出異常
    boolean add(E e);

    // 插入指定元素
    // 插入成功返回true;如果隊列沒有可用空間,返回false
    boolean offer(E e);

    // 獲取和刪除頭部元素
    // 如果隊列中沒有元素尼啡,拋出異常
    E remove();

    // 獲取和刪除頭部元素
    // 如果隊列中沒有元素,返回null
    E poll();

    // 獲取頭部元素
    // 如果隊列中沒有元素碴萧,拋出異常
    E element();

    // 獲取頭部元素
    // 如果隊列中沒有元素柒昏,返回null
    E peek();
}

2 BlockingQueue<E>接口

public interface BlockingQueue<E> extends Queue<E> {
    // 插入指定元素
    // 插入成功返回true;如果隊列沒有可用空間,拋出異常
    boolean add(E e);

    // 插入指定元素
    // 插入成功返回true茬故;如果隊列沒有可用空間盖灸,返回false
    boolean offer(E e);

    // 插入指定元素
    // 插入成功直接返回;如果隊列沒有可用空間磺芭,阻塞當前線程
    void put(E e) throws InterruptedException;

    // 插入指定元素
    // 插入成功返回true赁炎;如果隊列沒有可用空間,阻塞當前線程钾腺;如果在指定時間之內隊列一直沒有可用空間徙垫,返回false
    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;

    // 獲取和刪除頭部元素
    // 如果隊列中沒有元素,阻塞當前線程
    E take() throws InterruptedException;

    // 獲取和刪除頭部元素
    // 如果隊列中沒有元素垮庐,阻塞當前線程松邪;如果在指定時間之內隊列中一直沒有元素,返回null
    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;

    // 獲取隊列的剩余容量
    int remainingCapacity();

    // 刪除指定元素
    // 如果隊列發(fā)生改變哨查,返回true
    boolean remove(Object o);

    // 判斷隊列中是否包含指定元素
    public boolean contains(Object o);

    // 刪除隊列中的全部元素逗抑,并將這些元素添加到指定集合中
    int drainTo(Collection<? super E> c);

    // 刪除隊列中指定數(shù)量的元素,并將這些元素添加到指定集合中
    int drainTo(Collection<? super E> c, int maxElements);
}

3 ArrayBlockingQueue

3.1 ArrayBlockingQueue的特點

(1)數(shù)據(jù)結構:數(shù)組寒亥。
(2)有界無界:有界邮府。
(3)出隊入隊:FIFO。

3.2 ArrayBlockingQueue的構造方法

    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }

    // 傳入的fair用于創(chuàng)建ReentrantLock
    public ArrayBlockingQueue(int capacity, boolean fair) {
        if (capacity <= 0)
            throw new IllegalArgumentException();
        this.items = new Object[capacity];
        lock = new ReentrantLock(fair);
        notEmpty = lock.newCondition();
        notFull =  lock.newCondition();
    }

    // 傳入的fair用于創(chuàng)建ReentrantLock
    public ArrayBlockingQueue(int capacity, boolean fair,
                              Collection<? extends E> c) {
        this(capacity, fair);

        final ReentrantLock lock = this.lock;
        lock.lock(); // 獲取鎖溉奕,保證可見性
        try {
            int i = 0;
            try {
                for (E e : c) {
                    checkNotNull(e);
                    items[i++] = e;
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new IllegalArgumentException();
            }
            count = i;
            putIndex = (i == capacity) ? 0 : i;
        } finally {
            lock.unlock();
        }
    }

4 LinkedBlockingQueue

4.1 LinkedBlockingQueue的特點

(1)數(shù)據(jù)結構:單向鏈表褂傀。
(2)有界無界:可選。
(3)出隊入隊:FIFO加勤。

4.2 LinkedBlockingQueue的構造方法

    public LinkedBlockingQueue() {
        this(Integer.MAX_VALUE);
    }

    public LinkedBlockingQueue(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
        last = head = new Node<E>(null);
    }

    public LinkedBlockingQueue(Collection<? extends E> c) {
        this(Integer.MAX_VALUE);
        final ReentrantLock putLock = this.putLock;
        putLock.lock(); // 獲取鎖仙辟,保證可見性
        try {
            int n = 0;
            for (E e : c) {
                if (e == null)
                    throw new NullPointerException();
                if (n == capacity)
                    throw new IllegalStateException("Queue full");
                enqueue(new Node<E>(e));
                ++n;
            }
            count.set(n);
        } finally {
            putLock.unlock();
        }
    }

5 SynchronousQueue

5.1 SynchronousQueue的特點

(1)SynchronousQueue是一個特殊的隊列,它不存儲任何元素鳄梅。
(2)一個線程向隊列中添加元素叠国,不會立即返回,直至另一個線程從隊列中獲取元素戴尸;一個線程從隊列中獲取元素粟焊,不會立即返回,直至另一個線程向隊列中添加元素孙蒙。
(3)這里的Synchronous是指讀線程和寫線程同步项棠。

5.2 SynchronousQueue中的構造方法

    public SynchronousQueue() {
        this(false);
    }

    public SynchronousQueue(boolean fair) {
        transferer = fair ? new TransferQueue<E>() : new TransferStack<E>();
    }

6 PriorityBlockingQueue

6.1 PriorityBlockingQueue的特點

(1)數(shù)據(jù)結構:數(shù)組。
(2)有界無界:無界挎峦。支持自動擴容香追,最大容量為Integer.MAX_VALUE - 8。
(3)出隊入隊:優(yōu)先級大小坦胶。

6.2 PriorityBlockingQueue中的構造方法

    // DEFAULT_INITIAL_CAPACITY為11
    public PriorityBlockingQueue() {
        this(DEFAULT_INITIAL_CAPACITY, null);
    }

    public PriorityBlockingQueue(int initialCapacity) {
        this(initialCapacity, null);
    }

    public PriorityBlockingQueue(int initialCapacity,
                                 Comparator<? super E> comparator) {
        if (initialCapacity < 1)
            throw new IllegalArgumentException();
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        this.comparator = comparator;
        this.queue = new Object[initialCapacity];
    }

    public PriorityBlockingQueue(Collection<? extends E> c) {
        this.lock = new ReentrantLock();
        this.notEmpty = lock.newCondition();
        // heapify表示是否進行堆排序
        boolean heapify = true;
        // screen表示是否檢查集合中的元素
        boolean screen = true;
        if (c instanceof SortedSet<?>) {
            SortedSet<? extends E> ss = (SortedSet<? extends E>) c;
            this.comparator = (Comparator<? super E>) ss.comparator();
            heapify = false;
        }
        else if (c instanceof PriorityBlockingQueue<?>) {
            PriorityBlockingQueue<? extends E> pq =
                (PriorityBlockingQueue<? extends E>) c;
            this.comparator = (Comparator<? super E>) pq.comparator();
            screen = false;
            // 如果類型匹配
            if (pq.getClass() == PriorityBlockingQueue.class)
                heapify = false;
        }
        Object[] a = c.toArray();
        int n = a.length;
        // If c.toArray incorrectly doesn't return Object[], copy it.
        if (a.getClass() != Object[].class)
            a = Arrays.copyOf(a, n, Object[].class);





        // 如果集合是PriorityBlockingQueue翅阵,不檢查集合中的元素
        // 如果集合是SortedSet并且集合中只有一個元素歪玲,檢查集合中的元素
        // 如果集合是SortedSet并且集合中含有多個元素并且SortedSet中的comparator不等于null,檢查集合中的元素
        // 如果集合是SortedSet并且集合中含有多個元素并且SortedSet中的comparator等于null掷匠,不檢查集合中的元素
        // 如果集合既不是PriorityBlockingQueue又不是SortedSet并且集合中只有一個元素滥崩,檢查集合中的元素
        // 如果集合既不是PriorityBlockingQueue又不是SortedSet并且集合中含有多個元素,不檢查集合中的元素



        if (screen && (n == 1 || this.comparator != null)) {
            for (int i = 0; i < n; ++i)
                if (a[i] == null)
                    throw new NullPointerException();
        }
        this.queue = a;
        this.size = n;
        if (heapify)
            heapify();
    }

7 DelayQueue

一個使用優(yōu)先級隊列實現(xiàn)的無界阻塞隊列讹语。

    public DelayQueue() {}

    public DelayQueue(Collection<? extends E> c) {
        this.addAll(c);
    }

8 LinkedTransferQueue

一個由鏈表結構組成的無界阻塞隊列钙皮。

9 LinkedBlockingDeque

一個由鏈表結構組成的雙向阻塞隊列。

    public LinkedBlockingDeque() {
        this(Integer.MAX_VALUE);
    }

    public LinkedBlockingDeque(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
    }

    public LinkedBlockingDeque(Collection<? extends E> c) {
        this(Integer.MAX_VALUE);
        final ReentrantLock lock = this.lock;
        lock.lock(); // 獲取鎖顽决,保證可見性
        try {
            for (E e : c) {
                if (e == null)
                    throw new NullPointerException();
                if (!linkLast(new Node<E>(e)))
                    throw new IllegalStateException("Deque full");
            }
        } finally {
            lock.unlock();
        }
    }

ArrayBlockingQueue 底層是數(shù)組短条,有界隊列,如果我們要使用生產(chǎn)者-消費者模式才菠,這是非常好的選擇茸时。

LinkedBlockingQueue 底層是鏈表,可以當做無界和有界隊列來使用赋访,所以大家不要以為它就是無界隊列可都。

SynchronousQueue 本身不帶有空間來存儲任何元素,使用上可以選擇公平模式和非公平模式蚓耽。

PriorityBlockingQueue 是無界隊列渠牲,基于數(shù)組,數(shù)據(jù)結構為二叉堆步悠,數(shù)組第一個也是樹的根節(jié)點總是最小值签杈。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鼎兽,隨后出現(xiàn)的幾起案子答姥,更是在濱河造成了極大的恐慌,老刑警劉巖谚咬,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹦付,死亡現(xiàn)場離奇詭異,居然都是意外死亡序宦,警方通過查閱死者的電腦和手機睁壁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進店門背苦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來互捌,“玉大人,你說我怎么就攤上這事行剂★踉耄” “怎么了?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵厚宰,是天一觀的道長腌巾。 經(jīng)常有香客問我遂填,道長,這世上最難降的妖魔是什么澈蝙? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任吓坚,我火速辦了婚禮,結果婚禮上灯荧,老公的妹妹穿的比我還像新娘礁击。我一直安慰自己,他們只是感情好逗载,可當我...
    茶點故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布哆窿。 她就那樣靜靜地躺著,像睡著了一般厉斟。 火紅的嫁衣襯著肌膚如雪挚躯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天擦秽,我揣著相機與錄音码荔,去河邊找鬼。 笑死号涯,一個胖子當著我的面吹牛目胡,可吹牛的內容都是我干的。 我是一名探鬼主播链快,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼誉己,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了域蜗?” 一聲冷哼從身側響起巨双,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎霉祸,沒想到半個月后筑累,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡丝蹭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年慢宗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奔穿。...
    茶點故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡镜沽,死狀恐怖,靈堂內的尸體忽然破棺而出贱田,到底是詐尸還是另有隱情缅茉,我是刑警寧澤,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布男摧,位于F島的核電站蔬墩,受9級特大地震影響译打,放射性物質發(fā)生泄漏。R本人自食惡果不足惜拇颅,卻給世界環(huán)境...
    茶點故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一奏司、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧樟插,春花似錦结澄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至猜扮,卻和暖如春勉吻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旅赢。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工齿桃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人煮盼。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓短纵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親僵控。 傳聞我的和親對象是個殘疾皇子香到,可洞房花燭夜當晚...
    茶點故事閱讀 43,554評論 2 349