【經典】實現一個阻塞隊列

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class BlockingQueue<T> {

    /**
     * 對象池
     */
    private Object[] objs;

    /**
     * 容量
     */
    private int capacity = DEFAULT_CAPACITY;

    /**
     * 存元素的索引
     */
    private int putIndex = 0;

    /**
     * 取元素的索引
     */
    private int takeIndex = 0;

    /**
     * 元素個數
     */
    private int curLen = 0;

    /**
     * 併發鎖
     */
    private Lock lock = new ReentrantLock();

    /**
     * 隊列有元素
     */
    private Condition notNullCondition = lock.newCondition();

    /**
     * 隊列有空間
     */
    private Condition notFullCondition = lock.newCondition();

    /**
     * 默認容量大小
     */
    private static final int DEFAULT_CAPACITY = 100;

    public BlockingQueue(int capacity) {
        if (capacity > 0) {
            this.capacity = capacity;
        }

        objs = new Object[this.capacity];
    }

    public void push(T obj) throws InterruptedException {
        try {
            lock.lock();

            // 容量已滿,阻塞等待
            while (curLen == capacity) {
                System.out.println("Queue is full...");
                notFullCondition.await();
            }

            // 放置元素
            objs[putIndex] = obj;
            curLen++;

            // 索引更新
            putIndex++;
            if (putIndex >= capacity) {
                putIndex = 0;
            }

            // 通知消費者線程
            notNullCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public T poll() throws InterruptedException {
        Object obj;
        try {
            lock.lock();

            // 隊列未空,阻塞等待
            while (curLen == 0) {
                System.out.println("Queue is empty...");
                notNullCondition.await();
            }

            // 獲取元素
            obj = objs[takeIndex];
            curLen--;

            // 索引更新
            takeIndex++;
            if (takeIndex >= capacity) {
                takeIndex = 0;
            }

            // 通知生產者線程
            notFullCondition.signalAll();
        } finally {
            lock.unlock();
        }
        return (T) obj;
    }

    public static void main(String args[]) throws InterruptedException {
        BlockingQueue queue = new BlockingQueue(5);

        // 正常的入隊、出隊
        queue.push(1);
        System.out.println(queue.poll());
        queue.push(2);
        System.out.println(queue.poll());
        queue.push(3);
        System.out.println(queue.poll());

        // 持續入隊
        queue.push(1);
        queue.push(2);
        queue.push(3);
        queue.push(4);
        queue.push(5);
        // 這裏會阻塞
        // queue.push(6);

        // 持續出隊
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        System.out.println(queue.poll());
        // 這裏會阻塞
        // System.out.println(queue.poll());
    }

}

 

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