7.1 基本概念
队列(queue) :是只允许在一端(头部: front)进行插入操作,而在另一端==(尾部:rear)==进行删除操作的线性表。
特点:队列是一种先进先出(First In First Out)的线性表,简称FIFO。允许插入的一端为队尾,允许删除的一端称为对头。
7.2 BlockingQueue
阻塞:必须要阻塞、不得不阻塞
阻塞队列是一个队列,在数据结构中起的作用如下图
- 当队列是空的,从队列中获取元素的操作将会被阻塞。
- 当队列是满的,从队列中添加元素的操作将会被阻塞。
- 试图从空的队列中获取元素的线程将会被阻塞,直到其他线程往空的队列插入新的元素。
- 试图向已满的队列中添加新元素的线程将会被阻塞,直到其他线程从队列中移除一个或多个元素或者完全清空,使队列变得空闲起来并后续新增。
7.2.1 阻塞队列的用处
在多线程领域:所谓阻塞,在某些情况下会挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤起。
好处是不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程,因为这一切BlockingQueue 都可以处理好。
7.3 接口架构
7.3.1 接口架构图

- ArrayBlockingQueue:由数组结构组成的有界阻塞队列。
- LinkedBlockingQueue:由链表结构组成的有界(默认值为:integer.MAX_VALUE)阻塞队列。
7.3.2 常用API
方法\处理方法 | 抛出异常 | 返回特殊值 | 一直阻塞 | 超时退出 |
---|---|---|---|---|
插入方法 | add(e) | offer(e) | put(e) | offer(e, time, unit) |
移除方法 | remove( ) | poll( ) | take( ) | poll(time, unit) |
检查方法 | element( ) | peek( ) | 不可用 | 不可用 |
抛出异常
package cn.guardwhy.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
/*
抛出异常
*/
public class BlockingQueueDemo01 {
public static void main(String[] args) {
// 1.队列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
// 2.添加元素
System.out.println(blockingQueue.add("kobe"));
System.out.println(blockingQueue.add("curry"));
System.out.println(blockingQueue.add("James"));
// java.lang.IllegalStateException: Queue full
// System.out.println(blockingQueue.add("Durant"));
System.out.println("=========");
System.out.println("队首元素:" + blockingQueue.element()); // 查看队首元素?
// 3.出队操作
System.out.println("=========");
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
System.out.println(blockingQueue.remove());
// java.util.NoSuchElementException,抛出异常
// System.out.println(blockingQueue.remove());
}
}
返回特殊值
package cn.guardwhy.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
public class BlockingQueueDemo02 {
public static void main(String[] args) {
// 1.队列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
// 2.添加元素
System.out.println(blockingQueue.offer("kobe"));
System.out.println(blockingQueue.offer("curry"));
System.out.println(blockingQueue.offer("James"));
System.out.println(blockingQueue.offer("Durant"));
System.out.println("=========");
System.out.println("队首元素:" + blockingQueue.peek()); // 查看队首元素?
// 3.出队操作
System.out.println("=========");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll()); // null 不抛出异常
}
}
一直阻塞
package cn.guardwhy.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
public class BlockingQueueDemo03 {
public static void main(String[] args) throws InterruptedException {
// 1.队列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
// 2.添加元素
blockingQueue.put("kobe");
blockingQueue.put("Durant");
blockingQueue.put("James");
// blockingQueue.put("curry"); 一直阻塞
// 3.出队操作
System.out.println("=========");
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
System.out.println(blockingQueue.take());
// System.out.println(blockingQueue.take());// 阻塞不停止等待
}
}
超时退出
package cn.guardwhy.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
public class BlockingQueueDemo04 {
public static void main(String[] args) throws InterruptedException {
// 1.队列的大小
ArrayBlockingQueue blockingQueue = new ArrayBlockingQueue(3);
// 2.添加元素
blockingQueue.offer("kobe");
blockingQueue.offer("Durant");
blockingQueue.offer("James");
blockingQueue.offer("curry", 3, TimeUnit.SECONDS); // 等待超过3秒就退出
// 3.出队操作
System.out.println("=========");
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll());
System.out.println(blockingQueue.poll(3, TimeUnit.SECONDS));// 等待超过3s就退出
}
}
7.4 SynchronousQueue
7.4.1 同步队列
SynchronousQueue是BlockingQueue的实现类。SynchronousQueue 没有容量,与其他的 BlockingQueue 不同,SynchronousQueue是一个不存储元素的 BlockingQueue ,每一个put操作必须要等待一个take操作,否则不能继续添加元素。
7.4.2 代码示例
package cn.guardwhy.BlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
public class SynchronousQueueDemo05 {
public static void main(String[] args) {
// 1.创建队列
BlockingQueue<String> blockingQueue = new SynchronousQueue<>();
// 2.添加元素
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName() + "1");
blockingQueue.put(" curry");
System.out.println(Thread.currentThread().getName() + "2");
blockingQueue.put(" kobe");
System.out.println(Thread.currentThread().getName() + "3");
blockingQueue.put(" james");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "NBA").start();
new Thread(()->{
// 延迟3s
try {
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + blockingQueue.take());
TimeUnit.SECONDS.sleep(3);
System.out.println(Thread.currentThread().getName() + blockingQueue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
},"NBA").start();
}
}
执行结果