BlockingQueue译为阻塞队列 ,它是JDK 1.5添加的新的工具类,它继承于Queue队列,并扩展了Queue的功能。
BlockingQueue在检索元素时会等待队列变成非空,并在存储元素时会等待队列变为可用。
BlockingQueue的方法有四种实现形式,以不同的方式来处理。
- 第一种是抛出异常
- 特殊值:第二种是根据情况会返回null或者false
- 阻塞:第三种是无限期的阻塞当前线程直到操作变为可用后
- 超时:第四种是给定一个最大的超时时间,超过后才会放弃
BlockingQueue不允许添加null元素,在其实现类的方法add、put 或者offer后时添加null 会抛出空指针异常。BlockingQueue 会有容量限制。在任意时间内,它都会有一个remainCapacity,超过该值之前,任意put元素都会阻塞。
BlockingQueue 一般用于实现生产者一消费者队列,如下图所示
实现代码
package com.lxd;
import java.util.concurrent.ArrayBlockingQueue;
public class BlockingQueueDemo {
static ArrayBlockingQueue<String> abq = new ArrayBlockingQueue(2);
public static void main(String[] args) {
// 生产者
for (int i = 0; i < 3; i++) {
new Thread(() -> producer(), "producerThread" + i).start();
}
// 消费者
for (int i = 0; i < 3; i++) {
new Thread(() -> consumer(), "consumerThread" + i).start();
}
}
private static void consumer() {
while (true) {
try {
String msg = abq.take();
System.out.println(Thread.currentThread().getName() + " ->receive msg:" + msg);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private static void producer() {
for (int i = 0; i < 100; i++) {
try {
abq.put("[" + i + "]");
System.out.println(Thread.currentThread().getName() + " ->send msg:" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
BlockingQueue有多种实现,其中LinkedBlockingQueue 和ArrayBlockingQueue 是FIFO先入先出队列,二者分别和LinkedList和ArrayList 对应,比同步List具有更好的并发性能。PriorityBlockingQueue是一个优先级排序的阻塞队列,如果你希望按照某种顺序而不是FIFO处理元素时这个队列将非常有用。正如其他有序的容器一样, PriorityBlockingQueue 既可以按照自然顺序来比较元素,也可以使用Comparator比较器进行外部元素比较。SynchronousQueue 它维护的是一 组线程而不是一 组队列,实际上它不是一个队列,它的每个insert 操作必须等待其他相关线程的remove方法后才能执行,反之亦然。
LinkedBlockingQueue
它是一种基于链表的构造、先入先出的有界阻塞队列。队列的head 也就是头元素是 在队列中等待时间最长的元素;队列的tail 也就是队尾元素是队列中等待时间最短的元素。新的元素会被插入到队尾中,检索操作将获取队列中的头部元素。链表队列通常比基于数组的队列具有更高的吞吐量;但是在大多数并发应用程序中,可预测的性能较差。
ArrayBlockingQueue
ArrayBlockingQueue是一个用数组实现的有界队列,此队列顺序按照先入先出的原则对元素进行排序。默认情况下不保证线程公平的访问队列,所谓公平访问队列指的是阻塞的线程,可以按照阻塞的先后顺序访问,即先阻塞线程先访问队列。非公平性是对先等待的线程是非公平的。有可能先阻塞的线程最后才访问队列。
PriorityBlockingQueue
PriorityBlockingQueue是一 个支持优先级的阻塞队列,默认情况下的元素采取自然顺序生序或者降序,也可以自己定义Comparator进行外部排序。但需要注意的是不能保证同优先级元素的顺序。