一、什么是阻塞队列
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。 这两个附加的操作支持阻塞的插入和移除方法 1)支持阻塞的插入方法:意思是当队列满时,队列会阻塞插入元素的线程,直到队列不满。 2)支持阻塞的移除方法:意思是在队列为空时,获取元素的线程会等待队列变为非空 阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。 阻塞队列就是生产者用来存放元素、消费者用来获取元素的容器。
二、常见阻塞队列
ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列;
LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列;
PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列;
DelayQueue:一个使用优先级队列实现的无界阻塞队列;
SynchronousQueue:一个不存储元素的阻塞队列;
LinkedTransferQueue:一个由链表结构组成的无界阻塞队列(实现了继承于 BlockingQueue 的 TransferQueue);
LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列;
三、阻塞队列的操作方法
BlockingQueue 有四种形式的 API。
方法类型 |
抛出异常 |
返回特殊值 |
一直阻塞 |
超时退出 |
插入 |
add(e) |
offer(e) |
put(e) |
offer(e,time,unit) |
移除(取出) |
remove() |
poll() |
take() |
poll(time,unit) |
检查 |
element() |
peek() |
不可用 |
不可用 |
以 ArrayBlockingQueue 为例
1、add(e)
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(2); for (int i = 0; i < 3; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //add插入元素,队列满时,抛出异常java.lang.IllegalStateException: Queue full boolean add = blockingQueue.add(substring); System.out.println(add); } }
2、offer(e)
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(2); for (int i = 0; i < 3; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //offer无参构造,插入元素,队列满时,返回false boolean offer = blockingQueue.offer(substring); System.out.println(offer); } }
3、put(e)
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(2); for (int i = 0; i < 3; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //队列满时,阻塞线程 blockingQueue.put(substring); System.out.println((i+1)+"队列长度:"+blockingQueue.size()); } }
4、offer(e,time,unit)
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue=new ArrayBlockingQueue<>(2); for (int i = 0; i < 3; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //队列满时,等待5秒,重试一次 blockingQueue.offer(substring, 5,TimeUnit.SECONDS); System.out.println((i+1)+"队列长度:"+blockingQueue.size()); } }
5、remove()
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(2); for (int i = 0; i < 2; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //add插入元素,队列满时,抛出异常java.lang.IllegalStateException: Queue full blockingQueue.add(substring); } for (int i = 0; i < 3; i++) { //移除一个元素,当队列为空,java.util.NoSuchElementException System.out.println(blockingQueue.remove()); } }
6、poll()
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(2); for (int i = 0; i < 2; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //add插入元素,队列满时,抛出异常java.lang.IllegalStateException: Queue full blockingQueue.add(substring); } for (int i = 0; i < 3; i++) { //移除一个元素,当队列为空,返回null System.out.println(blockingQueue.poll()); } }
7、take()
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(2); for (int i = 0; i < 2; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //add插入元素,队列满时,抛出异常java.lang.IllegalStateException: Queue full blockingQueue.add(substring); } for (int i = 0; i < 3; i++) { //移除一个元素,当队列为空,阻塞线程 System.out.println(blockingQueue.take()); } }
8、poll(time,unit)
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(2); for (int i = 0; i < 2; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //add插入元素,队列满时,抛出异常java.lang.IllegalStateException: Queue full blockingQueue.add(substring); } for (int i = 0; i < 3; i++) { //移除一个元素,当队列为空,阻塞1s System.out.println(blockingQueue.poll(1, TimeUnit.SECONDS)); } }
9.element()、peek()
public static void main(String[] args) throws InterruptedException { BlockingQueue<String> blockingQueue = new ArrayBlockingQueue<>(2); for (int i = 0; i < 2; i++) { String substring = UUID.randomUUID().toString().substring(0, 8); //add插入元素,队列满时,抛出异常java.lang.IllegalStateException: Queue full blockingQueue.add(substring); } System.out.println(JSON.toJSONString(blockingQueue)); for (int i = 0; i < 2; i++) { //移除一个元素,当队列为空,返回null System.out.println(blockingQueue.remove()); } //检查队列,返回队列头部元素,如果队列为空返回null System.out.println(blockingQueue.peek()); //检查队列,返回队列先头部元素,如果队列为空返回java.util.NoSuchElementException System.out.println(blockingQueue.element()); }