阻塞队列之ArrayBlockingQueue

BlockingQueue 是一个接口,继承自Queue,已知实现类有以下几种:

一、ArrayBlockingQueue 有数组结构组成的有界阻塞队列

1、构造方法

在ArrayBlockingQueue类中有下面的3个构造方法:

1.1、 ArrayBlockingQueue(int)
    public ArrayBlockingQueue(int capacity) {
        this(capacity, false);
    }

1.2、ArrayBlockingQueue(int, boolean)
   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();
    }
1.3、ArrayBlockingQueue(int, boolean, Collection)
public ArrayBlockingQueue(int capacity, boolean fair,
                              Collection c) {
        this(capacity, fair);

        final ReentrantLock lock = this.lock;
        lock.lock(); // Lock only for visibility, not mutual exclusion
        try {
            int i = 0;
            try {
                for (E e : c) {
                    checkNotNull(e);
                    items[i++] = e;
                }
            } catch (ArrayIndexOutOfBoundsException ex) {
                throw new IllegalArgumentException();
            }
            count = i;
            putIndex = (i == capacity) ? 0 : i;
        } finally {
            lock.unlock();
        }
    }

ArrayBlockingQueue 默认情况下不能保证线程访问队列的公平性,所谓公平性是指严格按照线程等待的绝对时间顺序,即最先等待的线程能够最先访问到 ArrayBlockingQueue。而非公平性则是指访问 ArrayBlockingQueue 的顺序不是遵守严格的时间顺序,有可能存在,当 ArrayBlockingQueue 可以被访问时,长时间阻塞的线程依然无法访问到 ArrayBlockingQueue

通过上面的三个构造方法可以构造一个ArrayBlockingQueue的队列,在构造方法中初始化了实列变量,下面是一些实例变量。

    /** 保存队列的元素数组 */
    final Object[] items;

    /**取出元素的位置 */
    int takeIndex;

    /** 添加元素的位置 */
    int putIndex;

    /**队列中元素的数量*/
    int count;

    /*
     * Concurrency control uses the classic two-condition algorithm
     * found in any textbook.
     */

    /** 锁对象 */
    final ReentrantLock lock;

    /** 不空的信号 */
    private final Condition notEmpty;

    /** 不满的信号量 */
    private final Condition notFull;

    /**
     * Shared state for currently active iterators, or null if there
     * are known not to be any.  Allows queue operations to update
     * iterator state.
     */
    transient Itrs itrs = null;

2、队列的操作

2.1 add/peek

add/peek是一对互斥操作,add向队列放入元素,peek从队列取出元素;

2.1.1、add
    public boolean add(E e) {
        return super.add(e);
    }

    public boolean add(E e) {
        if (offer(e))
            return true;
        else
            throw new IllegalStateException("Queue full");
    }
    public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }
2.1.2、peek
   public E peek() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return itemAt(takeIndex); // 队列没有元素,返回null
        } finally {
            lock.unlock();
        }
    }
2.2、put/take

put/take是一对互斥的操作,put向队列种放入元素,take取出元素,其实现方式和add/peek不一样。

2.2.1、put()
    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();
        }
    }
    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();
    }
2.2.2、take()
    public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return dequeue();
        } finally {
            lock.unlock();
        }
    }
 private E dequeue() {
        // assert lock.getHoldCount() == 1;
        // assert items[takeIndex] != null;
        final Object[] items = this.items;
        @SuppressWarnings("unchecked")
        E x = (E) items[takeIndex];
        items[takeIndex] = null;
        if (++takeIndex == items.length)
            takeIndex = 0;
        count--;
        if (itrs != null)
            itrs.elementDequeued();
        notFull.signal();
        return x;
    }
2.3、offer(E)/poll()
2.3.1 offer(E)
    public boolean offer(E e) {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            if (count == items.length)
                return false;
            else {
                enqueue(e);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }
2.3.2 poll()
    public E poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return (count == 0) ? null : dequeue();
        } finally {
            lock.unlock();
        }
    }
2.4、 offer(E, long, TimeUnit) 和 poll(long, TimeUnit)

这两个方法是普通offer/poll方法的加强版,在队列满时指定了重试的时间,如果超过指定的时间后还是无法添加或取出则返回false。

2.4.1 offer(E, long, TimeUnit)
 public boolean offer(E e, long timeout, TimeUnit unit)
        throws InterruptedException {

        checkNotNull(e);
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length) {
                if (nanos <= 0)
                    return false;
                nanos = notFull.awaitNanos(nanos);
            }
            enqueue(e);
            return true;
        } finally {
            lock.unlock();
        }
    }
2.4.2 poll(long, TimeUnit)
  public E poll(long timeout, TimeUnit unit) throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0) {
                if (nanos <= 0)
                    return null;
                nanos = notEmpty.awaitNanos(nanos);
            }
            return dequeue();
        } finally {
            lock.unlock();
        }
    }

3 比较

3.1 添加方法比较
序号 方法名 队列满时处理方式 方法返回值
1 add(E e) 抛出“Queue full”异常 boolean
2 offer(E e) 返回false boolean
3 put(E e) 线程阻塞,直到中断或被唤醒 void
4 offer(E e, long timeout, TimeUnit unit) 在规定时间内重试,超过规定时间返回false boolean
3.2 取出方法比较
序号 方法名 队列满时处理方式 方法返回值
1 peek() 返回null E
2 poll() 返回null E
3 take() 线程阻塞,指定中断或被唤醒 E
4 poll(long timeout, TimeUnit unit) 在规定时间内重试,超过规定时间返回null E

你可能感兴趣的:(阻塞队列之ArrayBlockingQueue)