admin管理员组

文章数量:1599414

获取一个Condition必须通过Lock的newCondition()方法。下面通过一个有界队列的示例来 深入了解Condition的使用方式。有界队列是一种特殊的队列,当队列为空时,队列的获取操作 将会阻塞获取线程,直到队列中有新增元素,当队列已满时,队列的插入操作将会阻塞插入线 程,直到队列出现“空位”,


public class BoundedQueue<T> {
    private  Object[] items;
    // 添加的下标,删除的下标和数组当前数量
    private  int addIndex, removeIndex,count;
    private Lock lock=new ReentrantLock();
    private Condition notEmpty =lock.newCondition();
    private Condition notFull =lock.newCondition();
    public BoundedQueue (int size){
        items=new Object[size];
    }
    // 添加一个元素,如果数组满,则添加线程进入等待状态,直到有"空位
    public void add(T t)throws InterruptedException{
        lock.lock();
        try {
            while (count==items.length)
                notFull.await();
            items[addIndex]=t;
            if (++addIndex==items.length)
                addIndex=0;
            ++count;
            notEmpty.signal();
        }finally {
            lock.unlock();
        }

    }
    // 由头部删除一个元素,如果数组空,则删除线程进入等待状态,直到有新添加元素
    @SuppressWarnings("unchecked")
    public T remove() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();
            Object x = items[removeIndex];
            if (++removeIndex == items.length)
                removeIndex = 0;
            --count;
            notFull.signal();
            return (T) x;
        } finally {
            lock.unlock();
        }
    }
}

上述示例中,BoundedQueue通过add(T t)方法添加一个元素,通过remove()方法移出一个 元素。以添加方法为例。

  • 首先需要获得锁,目的是确保数组修改的可见性和排他性。

  • 当数组数量等于数组长度时, 表示数组已满,则调用notFull.await(),当前线程随之释放锁并进入等待状态。如果数组数量不等于数组长度,表示数组未满,则添加元素到数组中,同时通知等待在notEmpty上的线程,数组中已经有新元素可以获取。

  • 在添加和删除方法中使用while循环而非if判断,目的是防止过早或意外的通知,只有条件符合才能够退出循环。回想之前提到的等待/通知的经典范式,二者是非常类似的。

本文标签: 队列condition