java 中的阻塞隊列

一、什麼是阻塞隊列:java

  • 支持阻塞的插入方法,意思是當隊列滿時,隊列會阻塞插入元素的線程,知道隊列不滿。
  • 支持阻塞的移除方法:意思是在隊列爲空時,獲取元素的線程會等待隊列變爲非空。

  插入和移除操做的4種處理方式:數組

方法/處理方式  拋出異常  返回特殊值  一直阻塞  超時退出
插入方法 add(e) offer(e) put(e) offer(e, time, unit)
移除方法 remove() poll() take()  poll(time, unit)
檢查方法 element() peek()  不可用  不可用

二、java裏的阻塞隊列: 緩存

  1. ArrayBlockingQueue:是一個用數組實現的有界阻塞隊列。
  2. LinkedBlockingQueue:是一個永鏈表實現的有界阻塞隊列。
  3. PriorityBlockingQueue:是一個支持優先級的無界阻塞隊列。
  4. DealyQueue:是一個支持延時獲取元素的無界阻塞隊列。
  5. SynchronousQueue:是一個不存儲元素的阻塞隊列。每個put操做必須等待一個take操做,不然不能繼續添加元素。
  6. LinkedBlockingDeque是一個由鏈表結構組成的雙向阻塞隊列。
  7. LinkedTransferQueue:是一個由鏈表結構組成的無界阻塞TransferQueue隊列。

    重點:this

    DelayQueue很是有用,能夠將DelayQueue運用在如下應用場景。spa

    • 緩存系統的設計,能夠用DelayQueue保存緩存元素的有效期,使用一個線程循環查詢DelayQueue,一旦能獲取元素,標識緩存有效期到了。
    • 定時任務調度,使用DelayQueue保存當天將會執行的任務和執行時間。一旦從DelayQueue中獲取到任務就開始執行,好比TimerQueue就是使用此實現的。

三、阻塞隊列的實現原理:
  使用通知模式實現。所謂通知模式,就是當生產者往滿的隊列裏添加元素時會阻塞住生產者,當消費者消費了一個隊列中的元素後,會通知生產者當前隊列可用。查看ArrayBlockingQueue源碼發現使用了Condition來實現,代碼以下.線程

    private final Condition notEmpty;
    private final Condition notFull;

    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();
    }

    public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            enqueue(e);
        } finally {
            lock.unlock();
        }
    }

    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
    private void enqueue(E x) {
        // assert lock.getHoldCount() == 1;
        // assert items[putIndex] == null;
        final Object[] items = this.items;
        items[putIndex] = x;
        if (++putIndex == items.length)
            putIndex = 0;
        count++;
        notEmpty.signal();
    }
相關文章
相關標籤/搜索