java.util.concurrent系列之--LinkedBlockingDeque

1、LinkedBlockingDeque介紹

LinkedBlockingDeque是雙向鏈表實現的雙向併發阻塞隊列。該阻塞隊列同時支持FIFO和FILO兩種操做方html

式,便可以從隊列的頭和尾同時操做(插入/刪除);而且,該阻塞隊列是支持線程安全。數組

此外,LinkedBlockingDeque仍是可選容量的(防止過分膨脹),便可以指定隊列的容量。若是不指定,默認安全

容量大小等於Integer.MAX_VALUE。數據結構

2、LinkedBlockingDeque原理和數據結構

LinkedBlockingDeque的數據結構,以下圖所示:多線程

輸入圖片說明

說明:併發

1. LinkedBlockingDeque繼承於AbstractQueue,它本質上是一個支持FIFO和FILO的雙向的隊列。

2. LinkedBlockingDeque實現了BlockingDeque接口,它支持多線程併發。當多線程競爭同一個資源時,某

線程獲取到該資源以後,其它線程須要阻塞等待。ide

3. LinkedBlockingDeque是經過雙向鏈表實現的。

3.1 first是雙向鏈表的表頭。

3.2 last是雙向鏈表的表尾。

3.3 count是LinkedBlockingDeque的實際大小,即雙向鏈表中當前節點個數。

3.4 capacity是LinkedBlockingDeque的容量,它是在建立LinkedBlockingDeque時指定的。

3.5 lock是控制對LinkedBlockingDeque的互斥鎖,當多個線程競爭同時訪問LinkedBlockingDeque時,

某線程獲取到了互斥鎖lock,其它線程則須要阻塞等待,直到該線程釋放lock,其它線程纔有機會獲取lock函數

從而獲取cpu執行權。atom

3.6 notEmpty和notFull分別是「非空條件」和「未滿條件」。經過它們可以更加細膩進行併發控制。

注:

若某線程(線程A)要取出數據時,隊列正好爲空,則該線程會執行notEmpty.await()進行等待;當其它某個線線程

程(線程B)向隊列中插入了數據以後,會調用notEmpty.signal()喚醒「notEmpty上的等待線程」。此時,線程A

會被喚醒從而得以繼續運行。 此外,線程A在執行取操做前,會獲取takeLock,在取操做執行完畢再釋放

takeLock。

若某線程(線程H)要插入數據時,隊列已滿,則該線程會它執行notFull.await()進行等待;當其它某個線程(線

程I)取出數據以後,會調用notFull.signal()喚醒「notFull上的等待線程」。此時,線程H就會被喚醒從而得以繼

續運行。 此外,線程H在執行插入操做前,會獲取putLock,在插入操做執行完畢才釋放putLock。

3、LinkedBlockingDeque函數列表

// 建立一個容量爲 Integer.MAX_VALUE 的 LinkedBlockingDeque。
LinkedBlockingDeque()

// 建立一個容量爲 Integer.MAX_VALUE 的 LinkedBlockingDeque,最初包含給定 collection 的元素,以該 collection 迭代器的遍歷順序添加。
LinkedBlockingDeque(Collection<? extends E> c)

// 建立一個具備給定(固定)容量的 LinkedBlockingDeque。
LinkedBlockingDeque(int capacity)

// 在不違反容量限制的狀況下,將指定的元素插入此雙端隊列的末尾。
boolean add(E e)

// 若是當即可行且不違反容量限制,則將指定的元素插入此雙端隊列的開頭;若是當前沒有空間可用,則拋出 IllegalStateException。
void addFirst(E e)

// 若是當即可行且不違反容量限制,則將指定的元素插入此雙端隊列的末尾;若是當前沒有空間可用,則拋出 IllegalStateException。
void addLast(E e)

// 以原子方式 (atomically) 今後雙端隊列移除全部元素。
void clear()

// 若是此雙端隊列包含指定的元素,則返回 true。
boolean contains(Object o)

// 返回在此雙端隊列的元素上以逆向連續順序進行迭代的迭代器。
Iterator<E> descendingIterator()

// 移除此隊列中全部可用的元素,並將它們添加到給定 collection 中。
int drainTo(Collection<? super E> c)

// 最多今後隊列中移除給定數量的可用元素,並將這些元素添加到給定 collection 中。
int drainTo(Collection<? super E> c, int maxElements)

// 獲取但不移除此雙端隊列表示的隊列的頭部。
E element()

// 獲取,但不移除此雙端隊列的第一個元素。
E getFirst()

// 獲取,但不移除此雙端隊列的最後一個元素。
E getLast()

// 返回在此雙端隊列元素上以恰當順序進行迭代的迭代器。
Iterator<E> iterator()

// 若是當即可行且不違反容量限制,則將指定的元素插入此雙端隊列表示的隊列中(即此雙端隊列的尾部),並在成功時返回 true;若是當前沒有空間可用,則返回 false。
boolean offer(E e)

// 將指定的元素插入此雙端隊列表示的隊列中(即此雙端隊列的尾部),必要時將在指定的等待時間內一直等待可用空間。
boolean offer(E e, long timeout, TimeUnit unit)

// 若是當即可行且不違反容量限制,則將指定的元素插入此雙端隊列的開頭,並在成功時返回 true;若是當前沒有空間可用,則返回 false。
boolean offerFirst(E e)

// 將指定的元素插入此雙端隊列的開頭,必要時將在指定的等待時間內等待可用空間。
boolean offerFirst(E e, long timeout, TimeUnit unit)

// 若是當即可行且不違反容量限制,則將指定的元素插入此雙端隊列的末尾,並在成功時返回 true;若是當前沒有空間可用,則返回 false。
boolean offerLast(E e)

// 將指定的元素插入此雙端隊列的末尾,必要時將在指定的等待時間內等待可用空間。
boolean offerLast(E e, long timeout, TimeUnit unit)

// 獲取但不移除此雙端隊列表示的隊列的頭部(即此雙端隊列的第一個元素);若是此雙端隊列爲空,則返回 null。
E peek()

// 獲取,但不移除此雙端隊列的第一個元素;若是此雙端隊列爲空,則返回 null。
E peekFirst()

// 獲取,但不移除此雙端隊列的最後一個元素;若是此雙端隊列爲空,則返回 null。
E peekLast()

// 獲取並移除此雙端隊列表示的隊列的頭部(即此雙端隊列的第一個元素);若是此雙端隊列爲空,則返回 null。
E poll()

// 獲取並移除此雙端隊列表示的隊列的頭部(即此雙端隊列的第一個元素),若有必要將在指定的等待時間內等待可用元素。
E poll(long timeout, TimeUnit unit)

// 獲取並移除此雙端隊列的第一個元素;若是此雙端隊列爲空,則返回 null。
E pollFirst()

// 獲取並移除此雙端隊列的第一個元素,必要時將在指定的等待時間等待可用元素。
E pollFirst(long timeout, TimeUnit unit)

// 獲取並移除此雙端隊列的最後一個元素;若是此雙端隊列爲空,則返回 null。
E pollLast()
// 獲取並移除此雙端隊列的最後一個元素,必要時將在指定的等待時間內等待可用元素。
E pollLast(long timeout, TimeUnit unit)

// 今後雙端隊列所表示的堆棧中彈出一個元素。
E pop()

// 將元素推入此雙端隊列表示的棧。
void push(E e)

// 將指定的元素插入此雙端隊列表示的隊列中(即此雙端隊列的尾部),必要時將一直等待可用空間。
void put(E e)

// 將指定的元素插入此雙端隊列的開頭,必要時將一直等待可用空間。
void putFirst(E e)

// 將指定的元素插入此雙端隊列的末尾,必要時將一直等待可用空間。
void putLast(E e)

// 返回理想狀況下(沒有內存和資源約束)此雙端隊列可不受阻塞地接受的額外元素數。
int remainingCapacity()

// 獲取並移除此雙端隊列表示的隊列的頭部。
E remove()

// 今後雙端隊列移除第一次出現的指定元素。
boolean remove(Object o)

// 獲取並移除此雙端隊列第一個元素。
E removeFirst()

// 今後雙端隊列移除第一次出現的指定元素。
boolean removeFirstOccurrence(Object o)

// 獲取並移除此雙端隊列的最後一個元素。
E removeLast()

// 今後雙端隊列移除最後一次出現的指定元素。
boolean removeLastOccurrence(Object o)

// 返回此雙端隊列中的元素數。
int size()

// 獲取並移除此雙端隊列表示的隊列的頭部(即此雙端隊列的第一個元素),必要時將一直等待可用元素。
E take()

// 獲取並移除此雙端隊列的第一個元素,必要時將一直等待可用元素。
E takeFirst()

// 獲取並移除此雙端隊列的最後一個元素,必要時將一直等待可用元素。
E takeLast()

// 返回以恰當順序(從第一個元素到最後一個元素)包含此雙端隊列全部元素的數組。
Object[] toArray()

// 返回以恰當順序包含此雙端隊列全部元素的數組;返回數組的運行時類型是指定數組的運行時類型。
<T> T[] toArray(T[] a)

// 返回此 collection 的字符串表示形式。
String toString()

4、LinkedBlockingDeque示例

/*
*   LinkedBlockingDeque是「線程安全」的隊列,而LinkedList是非線程安全的。
*
*   下面是「多個線程同時操做而且遍歷queue」的示例
*   (01) 當queue是LinkedBlockingDeque對象時,程序能正常運行。
*   (02) 當queue是LinkedList對象時,程序會產生ConcurrentModificationException異常。
*
* @author skywang
*/
public class LinkedBlockingDequeDemo1 {

    // TODO: queue是LinkedList對象時,程序會出錯。
    //private static Queue<String> queue = new LinkedList<String>();
    private static Queue<String> queue = new LinkedBlockingDeque<String>();

    public static void main(String[] args) {

        // 同時啓動兩個線程對queue進行操做!
        new MyThread("ta").start();
        new MyThread("tb").start();
    }

    private static void printAll() {
        String value;
        Iterator iter = queue.iterator();
        while (iter.hasNext()) {
            value = (String) iter.next();
            System.out.print(value + ", ");
        }
        System.out.println();
    }

    private static class MyThread extends Thread {
        MyThread(String name) {
            super(name);
        }

        @Override
        public void run() {
            int i = 0;
            while (i++ < 6) {
                // 「線程名」 + "-" + "序號"
                String val = Thread.currentThread().getName() + i;
                queue.add(val);
                // 經過「Iterator」遍歷queue。
                printAll();
            }
        }
    }
}

5、結果說明:

示例程序中,啓動兩個線程(線程ta和線程tb)分別對LinkedBlockingDeque進行操做。以線程ta

而言,它會先獲取「線程名」+「序號」,而後將該字符串添加到LinkedBlockingDeque中;接着,遍歷並輸出

LinkedBlockingDeque中的所有元素。 線程tb的操做和線程ta同樣,只不過線程tb的名字和線程ta的名字不

同。

當queue是LinkedBlockingDeque對象時,程序能正常運行。若是將queue改成LinkedList時,程序會產生

ConcurrentModificationException異常。

6、轉載地址

http://www.cnblogs.com/skywang12345/p/3503480.html

相關文章
相關標籤/搜索