Summary
ArrayBlockingQueue is a bounded blocking queue based on array implementation. Follow the first in, first out FIFO principle to sort the elements. All elements enter the team from the tail and leave the team from the head.
1. Data structure
The length of the array based blocking queue must be set. The element cannot be empty, first in first out.
2, principle
ArrayBlockingQueue, a lock for reading and writing, means that all locking operations are mutually exclusive. When the queue is full, the put thread will block, and when the queue is empty, the take thread will block.
3. Source code interpretation
3.1 variable
ArrayBlockingQueue defines the array item to store data, the next index to be taken out, the next index to be added putIndex, the number of elements in the queue count, a lock, two condition objects notFull and notEmpty corresponding to read and write, and its to maintain the array sequence.
3.2 construction method
There are three construction methods for ArrayBlockingQueue, as follows:
- Set the capacity size, and do not specify whether to use fair locks. The default is to use non fair locks;
- Set the capacity size and specify the lock type;
- To import the elements in the Collection into the queue, the put(E x) method is actually used. Later, the put method will be described in detail, which will not be described in detail here.
3.3 put(E x) joining method
Enter the queue in order. If the queue is full, enter the queue to wait.
public void put(E e) throws InterruptedException { //Element discrimination checkNotNull(e); final ReentrantLock lock = this.lock; //The difference between acquiring exclusive lock and lock() method is that it can throw an exception to jump out when it is blocked lock.lockInterruptibly(); try { //If the queue is full, enter the queue waiting thread queue and wait while (count == items.length) notFull.await(); //Please refer to the following entry operation for details enqueue(e); } finally { //Release lock lock.unlock(); } } private void enqueue(E x) { final Object[] items = this.items; items[putIndex] = x; //Queue full, set putIndex to 0 if (++putIndex == items.length) putIndex = 0; count++;//Number of elements in the queue plus 1 notEmpty.signal();//Notify the thread in the queue waiting for the queue, the queue is not empty }
3.4 take (e x) method
If the queue is empty, it will enter the queue waiting thread queue.
public E take() throws InterruptedException { final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { //If the queue is empty, enter the queue waiting thread queue waiting while (count == 0) notEmpty.await(); // For details, please refer to the following team leaving method return dequeue(); } finally { lock.unlock(); } } private E dequeue() { final Object[] items = this.items; @SuppressWarnings("unchecked") E x = (E) items[takeIndex]; items[takeIndex] = null; //If the last element in the queue is taken, it is taken from position 0 if (++takeIndex == items.length) takeIndex = 0; count--;/Number of currently owned elements minus 1 // It is complex to maintain itrs parameters. If you are interested in it, you can further study it if (itrs != null) itrs.elementDequeued(); //Notify the thread in the queue to wait, and the queue is empty notFull.signal(); return x; }
3.4 iterator
Because the array has subscripts, the Iterator also maintains the location index of the elements, and the two are related, so every time the elements are removed, the parameters in the Iterator iterator need to be maintained. If you are interested, you can study the principle of Iterator.
summary
The ArrayBlockingQueue is relatively simple, and it is difficult to maintain the itrs part. If you are interested, you can study it. Its characteristics are as follows:
- Element cannot be empty. If it is empty, NullPointException exception will be thrown;
- The capacity of bounded queue must be set;
- The underlying data structure is array;
- The same lock is used for reading and writing, so it is a security class
- Reading and writing the same lock, which means that reading and writing can not be carried out at the same time, but because it is based on array implementation, the natural efficiency is very high;
- Every take operation needs to maintain the parameters in Iterator iterator;