自己動手實現BlockingQueue

    Java的java.util.concurrent.*包下有許多在併發場景下使用的集合,ArrayBlockingQueue是其中之一,它是一個循環隊列,這個隊列的特別之處在於take方法與put方法,分別對應隊列的元素出列和元素入列操作,當隊列爲空時,take會使得線程進入等待狀態,直到隊列不爲空,有元素能夠出列纔會繼續執行;同理,當隊列滿時,put方法也會使得線程進入等待狀態。

    實際上這是一個生產者-消費者模型,按照理解, 自己也試着實現了一個,代碼如下

/**
 * Created by YotWei on 2018/7/1.
 */
public class BlockingQueue<E> {

    /**
     * 有界隊列內部固定長度,因此可以用數組實現
     */
    private Object[] elements;

    /**
     * 隊列的頭和尾下標
     */
    private int head = 0, tail = 0;

    /**
     * 隊列目前的長度
     */
    private int size;

    private ReentrantLock lock = new ReentrantLock();

    private Condition notEmpty = lock.newCondition();

    private Condition notFull = lock.newCondition();

    public BlockingQueue(int capacity) {
        this.elements = new Object[capacity];
    }

    public void put(E e) {
        lock.lock();
        try {
            while (size == elements.length)
                notFull.await();
            elements[tail] = e;
            if (++tail == elements.length) {
                tail = 0;
            }
            size++;
            notEmpty.signal();

        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public E take() {
        lock.lock();
        E e = null;
        try {
            while (size == 0) {
                notEmpty.await();
            }
            e = (E) elements[head];
            elements[head] = null;
            if (++head == elements.length)
                head = 0;
            size--;
            notFull.signal();

        } catch (InterruptedException ex) {
            ex.printStackTrace();
        } finally {
            lock.unlock();
        }
        return e;
    }

    public int size() {
        lock.lock();
        try {
            return size;
        } finally {
            lock.unlock();
        }
    }
}

    實際上ArrayBlockingQueue還包含許多其它方法,這兩個是最核心的。

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