parameter
public class ArrayBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
/**
* Serialization ID. This class relies on default serialization
* even for the items array, which is default-serialized, even if
* it is empty. Otherwise it could not be declared final, which is
* necessary here.
*/
private static final long serialVersionUID = -817911632652898426L;
/** queue Represented by an array*/
final Object[] items;
/** Where to take the next element from the queue*/
int takeIndex;
/** Where to insert the next item*/
int putIndex;
/** Number of item s in the queue*/
int count;
/*
* Concurrency control uses the classic two-condition algorithm
* found in any textbook.
*/
/** A reentry lock for synchronization */
final ReentrantLock lock;
/** Condition s waiting to get elements from the queue */
private final Condition notEmpty;
/** Condition s waiting to add elements from the queue */
private final Condition notFull;
}
Add item to queue
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)//If the array is full, it blocks, releases the lock, and enters the Waiting state
notFull.await();
final Object[] items = this.items;//If a thread takes an element from it, it will wake up the thread to continue execution
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
notEmpty.signal();//After execution, you need to wake up the threads that are getting elements from the array and continue
} finally {
lock.unlock();
}
}
Add item from queue
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)//If the array is empty, the thread that gets the element will enter the wait, and other threads that add the element will execute
notEmpty.await();
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();//Because the elements of the fetching thread have been executed, it is necessary to wake up the threads that cannot execute the addition because the array is full
return x;
} finally {
lock.unlock();
}
}
public class LinkedBlockingQueue<E> extends AbstractQueue<E>
implements BlockingQueue<E>, java.io.Serializable {
private static final long serialVersionUID = -6903933977591709194L;
//Static inner classes are used to store nodes
static class Node<E> {
E item;
Node<E> next;
Node(E x) { item = x; }
}
/** The capacity bound, or Integer.MAX_VALUE if none */
private final int capacity;
/** Elements in a linked list */
private final AtomicInteger count = new AtomicInteger();
/**
* Head of linked list, head.item = null
*/
transient Node<E> head;
/**
* Tail node of linked list, invariant last.next= null
*/
private transient Node<E> last;
/** Taking elements from a linked list requires a takeLock lock */
private final ReentrantLock takeLock = new ReentrantLock();
/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition();
/** Adding insert elements to a linked list requires a putLock lock*/
private final ReentrantLock putLock = new ReentrantLock();
/** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition();
private void signalNotEmpty() {
final ReentrantLock takeLock = this.takeLock;
takeLock.lock();
try {
notEmpty.signal();
} finally {
takeLock.unlock();
}
}
/**
*
*/
private void signalNotFull() {
final ReentrantLock putLock = this.putLock;
putLock.lock();
try {
notFull.signal();
} finally {
putLock.unlock();
}
}
}
Add elements from the queue and wait until the queue is full; once other threads get elements from the queue, they wake up the threads waiting to add elements
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
Get the element from the queue. If the queue is empty, it will wait all the time. Once another thread gets the element from the queue, it will wake up the thread waiting to add the element
public E take() throws InterruptedException {
E x;
int c = -1;
final AtomicInteger count = this.count;
final ReentrantLock takeLock = this.takeLock;
takeLock.lockInterruptibly();
try {
while (count.get() == 0) {
notEmpty.await();
}
x = dequeue();
c = count.getAndDecrement();
if (c > 1)
notEmpty.signal();
} finally {
takeLock.unlock();
}
if (c == capacity)
signalNotFull();
return x;
}