雙向阻塞隊列BlockingDeque

前言


前面我總結了一下關於BlockingQueue和BlockingQueue實現類的相關知識點,現在接下來看concurrent包的另一個接口BlockingDeque,BlockingDeque 接口表示一個線程安放入和提取實例的雙端隊列。就是說兩段都可以進出的,實際上和單端的也差不多,就是單端變雙端。

這裏寫圖片描述

拋異常 特定值 阻塞 超時
插入 addFirst(o) offerFirst(o) putFirst(o)
移除 removeFirst(o) pollFirst(o) takeFirst(o)
檢查 getFirst(o) peekFirst(o)

實現類


  • LinkedBlockingDeque

接口源碼


/*
    我把註釋全刪了
*/

package java.util.concurrent;
import java.util.*;

// Deque繼承了Queue
public interface BlockingDeque<E> extends BlockingQueue<E>, Deque<E> {

    void addFirst(E e);


    void addLast(E e);


    boolean offerFirst(E e);


    boolean offerLast(E e);


    void putFirst(E e) throws InterruptedException;


    void putLast(E e) throws InterruptedException;


    boolean offerFirst(E e, long timeout, TimeUnit unit)
        throws InterruptedException;


    boolean offerLast(E e, long timeout, TimeUnit unit)
        throws InterruptedException;


    E takeFirst() throws InterruptedException;


    E takeLast() throws InterruptedException;


    E pollFirst(long timeout, TimeUnit unit)
        throws InterruptedException;


    E pollLast(long timeout, TimeUnit unit)
        throws InterruptedException;


    boolean removeFirstOccurrence(Object o);


    boolean removeLastOccurrence(Object o);

    // *** BlockingQueue methods ***
    // 所以以下是BlockingQueue相關的方法

    boolean add(E e);


    boolean offer(E e);


    void put(E e) throws InterruptedException;


    boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException;


    E remove();


    E poll();


    E take() throws InterruptedException;


    E poll(long timeout, TimeUnit unit)
        throws InterruptedException;


    E element();


    E peek();


    boolean remove(Object o);


    public boolean contains(Object o);


    public int size();


    Iterator<E> iterator();

    // *** Stack methods ***


    void push(E e);
}

LinkedBlockingQueue


這個實現類只有一個,我就不另外開一章來講了,就看看這個就好了。

怎麼用?

import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque;

public class Main22 {
    public static void main(String[] args) {
        BlockingDeque<Integer> bd = new LinkedBlockingDeque<>();
        Pro pro = new Pro(bd);
        Con1 con = new Con1(bd);

        pro.start();
        con.start();
    }
}

class Pro extends Thread {
    private BlockingDeque<Integer> bd;

    public Pro(BlockingDeque<Integer> bd) {
        this.bd = bd;
    }

    @Override
    public void run() {
        try {
            bd.putFirst(1);
            // 不加這個延遲,幾乎是一個順序操作
            Thread.sleep(2);
            bd.putFirst(2);
            bd.putFirst(3);
            System.out.println(bd.toString());
            System.out.println(Thread.currentThread().getName() + "  " + bd.takeFirst());
            System.out.println(bd.toString());
            System.out.println(Thread.currentThread().getName() + "  " + bd.takeLast());
            System.out.println(bd.toString());
            System.out.println(Thread.currentThread().getName() + "  " + bd.take());

            bd.putFirst(4);
            bd.putFirst(5);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}



class Con1 extends Thread {
    private BlockingDeque<Integer> bd;

    public Con1(BlockingDeque<Integer> bd) {
        this.bd = bd;
    }

    @Override
    public void run() {
        try {
            bd.putLast(11);
            Thread.sleep(2);
            bd.putLast(22);
            bd.putLast(33);
            System.out.println(bd.toString());
            System.out.println(Thread.currentThread().getName() + "  " + bd.takeFirst());
            System.out.println(bd.toString());
            System.out.println(Thread.currentThread().getName() + "  " + bd.takeLast());
            System.out.println(bd.toString());
            System.out.println(Thread.currentThread().getName() + "  " + bd.take());

            bd.putLast(44);
            bd.putLast(55);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

結果

[3, 2, 1, 11]
Thread-0  3
[2, 1, 11]
Thread-0  11
[2, 1]
Thread-0  2
[5, 4, 1, 22, 33]
Thread-1  5
[4, 1, 22, 33]
Thread-1  33
[4, 1, 22]
Thread-1  4

看看源碼

public void putFirst(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        // 需要包裝一個Node
        Node<E> node = new Node<E>(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            while (!linkFirst(node))
                notFull.await();
        } finally {
            lock.unlock();
        }
}

private boolean linkFirst(Node<E> node) {
        // assert lock.isHeldByCurrentThread();
        // 如果比容量大返回false
        if (count >= capacity)
            return false;
        // 否則就把節點掛在最前面
        Node<E> f = first;
        node.next = f;
        first = node;
        if (last == null)
            last = node;
        else
            f.prev = node;
        ++count;
        notEmpty.signal();
        return true;
}

// 沒有指定容量就指定容量爲Max Integer
public LinkedBlockingDeque() {
        this(Integer.MAX_VALUE);
}

// 如果指定了容量,就以指定容量爲capacity
public LinkedBlockingDeque(int capacity) {
        if (capacity <= 0) throw new IllegalArgumentException();
        this.capacity = capacity;
    }

// 與put相似,不過是相反過程
public E takeLast() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            E x;
            while ( (x = unlinkLast()) == null)
                notEmpty.await();
            return x;
        } finally {
            lock.unlock();
        }
}

private E unlinkLast() {
        // assert lock.isHeldByCurrentThread();
        Node<E> l = last;
        if (l == null)
            return null;
        Node<E> p = l.prev;
        E item = l.item;
        l.item = null;
        l.prev = l; // help GC
        last = p;
        if (p == null)
            first = null;
        else
            p.next = null;
        --count;
        notFull.signal();
        return item;
}    

後記


其實這個BlockingDeque並不算很難,這只是滿足了一種需求而創造出來的,實質上還是屬於BlockingQueue範疇的東西。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章