一个队列在队空和队满的情况下进行出队和进队操作会发生阻塞,这种队列我们称之为阻塞队列.队列在队空的情况下进行出队操作会发生阻塞,直到有一到多个队项入队为止.队列在队满的情况下入队会发生阻塞,直到有队项出列或队空的情况下.
这是一个两个线程通过阻塞队列协作的示例图:

我们可以看出一个线程从队列中取出队项,一个线程往队列中放入对项.
Java5的java.util.concurrent包中已有现成的阻塞队列实现.但我们仍然很有必要知道它的底层实现原理.
阻塞队列实现
一个阻塞队列的实现看起来有点像BoundedSemaphore.如下一个简单的阻塞队列实现:
public class BlockingQueue<T> {
private List<T> queue = new ArrayList<>();
private int limit = 10;
public BlockingQueue(int limit) {
this.limit = limit;
}
public synchronized void enqueue(T item) {
while (queue.size() == limit) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (queue.size() == 0) {
notifyAll();
}
queue.add(item);
}
public synchronized T dequeue(){
while (queue.size() == 0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if(queue.size() == limit){
notifyAll();
}
return queue.remove(0);
}
}
我们可以注意到当调用enqueue()和dequeue()发现队满和队空时需要调用notifyAll()来唤醒相应的线程来取出和放入队项.如果队列大小没有达到限制,那么两个线程可以在不用阻塞线程的情况下放入和取出队项.
该系列博文为笔者复习基础所著译文或理解后的产物,复习原文来自Jakob Jenkov所著Java Concurrency and Multithreading Tutorial