ArrayBlockingQueue is an ArrayBlockingQueue that can be used to block a queue. ArrayBlockingQueue has the following features:

  • A bounded blocking queue implemented by an array. Once the capacity is created, the subsequent size cannot be modified.
  • Follow the fifO rule;
  • As with LinkedBlockingQueue, putting data to the queue is blocked when the queue is full, or taking data to the queue when the queue is empty;
  • Data operation, the same lock, so can not read and write operations at the same time;

ArrayBlockingQueue, like LinkedBlockingQueue, also extends the AbstractQueue implementation BlockingQueue interface, so in the same way as LinkedBlockingQueue, So instead of listing methods here, check out the previous LinkedBlockingQueue article

In addition to methods, there are two more important parameters in ArrayBlockingQueue:

/** items index for next take, poll, peek or remove */
// Get the position of the element
int takeIndex;
/** items index for next put, offer, or add */
// The array index of the new element
int putIndex;
Copy the code

ArrayBlockingQueue (ArrayBlockingQueue) : ArrayBlockingQueue (ArrayBlockingQueue) ArrayBlockingQueue (ArrayBlockingQueue)

ArrayBlockingQueue has three constructors:


public ArrayBlockingQueue(int capacity);
// fair indicates whether the lock is fair
public ArrayBlockingQueue(int capacity, boolean fair);

public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c);
Copy the code

ArrayBlockingQueue (ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue, ArrayBlockingQueue

Let’s start with the put() method and see how ArrayBlockingQueue is implemented

public void put(E e) throws InterruptedException {
    Objects.requireNonNull(e);
    / / acquiring a lock
    final ReentrantLock lock = this.lock;
    // Set a reentrant lock
    lock.lockInterruptibly();
    try {
        // When the array queue is full, block and wait.....
        while (count == items.length)
            notFull.await();
        // join the queue operation
        enqueue(e);
    } finally {
        / / unlocklock.unlock(); }}/ / team
private void enqueue(E e) {
    final Object[] items = this.items;
    // Insert the corresponding position according to putIndex
    items[putIndex] = e;
    // Set the next insertion position, if the current insertion position is the last element,
    // The next insertion position will be the head of the queue
    if (++putIndex == items.length) putIndex = 0;
    count++;
    notEmpty.signal();
}
Copy the code

The implementation of the put() method is fairly straightforward, with only about 20 lines of code. Let’s break down the put process:

  • 1. Obtain the lock first and lock the operation;
  • 2. Check whether the queue is full. If the queue is full, suspend the queue.
  • Insert elements directly into the Items array according to putIndex;
  • 4. Adjust the position of putIndex for the next insertion. If the current putIndex is the last position of the array, then the next insertion of putIndex is the first position of the array, which can be treated as a loop.
  • 5. Unlock;

Just like LinkedBlockingQueue, there are no other methods to add to it

ArrayBlockingQueue implements take(). ArrayBlockingQueue implements take().


public E take(a) throws InterruptedException {
    / / acquiring a lock
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        // Check whether the queue is empty, if so, suspend the wait
        while (count == 0)
            notEmpty.await();
        // Get data
        return dequeue();
    } finally{ lock.unlock(); }}private E dequeue(a) {
    
    final Object[] items = this.items;
    @SuppressWarnings("unchecked")
    // Get the elements in items according to takeIndex
    E e = (E) items[takeIndex];
    // Leave the data in takeIndex empty
    items[takeIndex] = null;
    // Set the index of the next fetch,
    if (++takeIndex == items.length) takeIndex = 0;
    count--;
    if(itrs ! =null)
        itrs.elementDequeued();
    notFull.signal();
    return e;
}
Copy the code

The take() method is not very different from the put() method

Finally, we will pay attention to remove() method, this method is still some knowledge, the main source is as follows:


public boolean remove(Object o) {
    if (o == null) return false;
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        if (count > 0) {
            final Object[] items = this.items;
            for (int i = takeIndex, end = putIndex,
                     to = (i < end) ? end : items.length;
                 ; i = 0, to = end) {
                 // Iterate over a valued piece of data
                for (; i < to; i++)
                    if (o.equals(items[i])) {
                        removeAt(i);
                        return true;
                    }
                if (to == end) break; }}return false;
    } finally{ lock.unlock(); }}// This is the method
void removeAt(final int removeIndex) {
    final Object[] items = this.items;
    // If the location to be deleted happens to be the location of the next take
    if (removeIndex == takeIndex) {
        // removing front item; just advance
        items[takeIndex] = null;
        if (++takeIndex == items.length) takeIndex = 0;
        count--;
        if(itrs ! =null)
            itrs.elementDequeued();
    } else {
        // If the delete position is between takeIndex and putIndex, the deleted data will be moved forward ~
        for (int i = removeIndex, putIndex = this.putIndex;;) {
            int pred = i;
            if (++i == items.length) i = 0;
            if (i == putIndex) {
                items[pred] = null;
                this.putIndex = pred;
                break;
            }
            items[pred] = items[i];
        }
        count--;
        if(itrs ! =null)
            itrs.removedAt(removeIndex);
    }
    notFull.signal();
}
Copy the code

There are three cases of remove:

  • First: when removeIndex == takeIndex, this situation is relatively simple, the location of the element removed, takeIndex +1 can be;

  • If removeIndex + 1 == putIndex, remove putIndex -1.

  • Third: when removeIndex! = takeIndex && removeIndex + 1 ! PutIndex = putIndex = putIndex = putIndex = putIndex = putIndex = putIndex = putIndex = putIndex

ArrayBlockingQueue – ArrayBlockingQueue – ArrayBlockingQueue – ArrayBlockingQueue – ArrayBlockingQueue

The last

Welcome to pay attention to the public number [Internet flathead brother], learn together, progress together ~