One: the concept of blocking queue
A blocking queue is a queue that supports two additional operations. These two additional operations support blocking insert and remove methods.
Blocking insert: put method, when the queue is full, the queue will block the thread that inserts the element until the queue is full.
Blocking removal: take method, when the queue is empty, the thread that gets the element will wait for the queue to become non-empty.
The BlockingQueue method comes in four forms. For operations that cannot be satisfied immediately but may be satisfied at some point in the future, these four forms are handled differently: the first is to throw an exception, and the second is to return a special value (null or false, depending on the operation), the third is to block the current thread indefinitely until the operation can succeed, and the fourth is to block only for a given maximum time limit before giving up.
|
Throw an exception |
special value |
block |
time out |
insert |
||||
remove |
||||
an examination |
unavailable |
unavailable |
Two: the characteristics of blocking queue
① Inserting null values is not allowed
BlockingQueue does not accept null elements. Some implementations throw NullPointerException when trying to add , put , or offer a null element . null is used as a guard value to indicate that the poll operation failed.
②Thread safety
The BlockingQueue implementation is thread safe. All queuing methods can use internal locks or other forms of concurrency control to achieve their purpose automatically
③Constant volume (with capacity)
BlockingQueue can be limited capacity. It can have a remainingCapacity at any given time , beyond which additional elements cannot be put non-blocking. A BlockingQueue without any internal capacity constraints always reports the remaining capacity of Integer.MAX_VALUE .
Three: Implementation class of blocking queue
①ArrayBlockingQueue
ArrayBlockingQueue is a bounded blocking queue implemented with arrays. The secondary queue sorts the elements on a first-in-first-out (FIFO) basis.
This class supports an optional fairness strategy for ordering waiting producer and consumer threads. By default, this ordering is not guaranteed. However, a queue constructed by setting fairness to true allows threads to be accessed in FIFO order. Fairness generally reduces throughput, but also reduces variability and avoids "imbalance".
ArrayBlockingQueue (int capacity) creates an ArrayBlockingQueue with the given (fixed) capacity and default access policy . |
ArrayBlockingQueue (int capacity, boolean fair) Creates an ArrayBlockingQueue with the given (fixed) capacity and the specified access policy . |
Visitor fairness is achieved using reentrant locks.
②LinedBlockingQueue
LinedBlockingQueue是一个用链表实现的有界阻塞队列。此队列的默认最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。
③PriorityBlockinQueue
PriorityBlockinQueue进行的操作不保证具有同等优先级的元素的顺序。如果需要实施某一排序,那么可以定义自定义类实现compareTo()方法或者比较器(Comparator),比较器可使用修改键断开主优先级值之间的联系。
④DelayQueue
DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口。创建元素时可以指定多久才可以从队列中获取当前元素。
DelayQueue可以应用的场景:缓存系统的设计、定时任务的调度。
实现Delayed接口:
long |
第一步:创建对象的时候,初始化基本数据。使用time记录当前对象延迟到什么时候可以使用,使用sequenceNumber来标识元素在队列中的先后顺序。
第二步:实现getDelay方法
第三步:实现compareTo方法指定元素的顺序。
⑤SynchronousQueue
SynchronousQueue是一个存储元素的阻塞队列每一个put操作必须等待一个take操作。
⑥LinkedBlockingDeque
LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列。所谓双向队列指的是可以从队列的两端插入和移除元素。
四:阻塞队列的实现原理
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
我们查看源代码,可以看出ArrayBlockingQueue使用了Condition来实现通知模式的。
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();
}
}
public E take() throws InterruptedException {
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == 0)
notEmpty.await();
return dequeue();
} finally {
lock.unlock();
}
}