一、阻塞队列
阻塞队列,首先是一个队列。当阻塞队列是空时,从队列中获取元素的操作将会被阻塞;当阻塞队列是满时,往队列里添加元素的操作将会被阻塞
在多线程领域,所谓阻塞,在某些情况下挂起线程(即阻塞),一旦条件满足,被挂起的线程又会自动被唤醒,我们不需要关心什么时候需要阻塞线程,什么时候需要唤醒线程
二、BlockingQueue核心方法
方法类型 | 抛出异常 | 特殊值 | 阻塞 | 超时 |
插入 | add(e) | offer(e) | put(e) | offer(e, time, unit) |
移除 | remove() | poll() | take() | poll(time, unit) |
检查 | element() | peek() | 不可用 | 不可用 |
抛出异常:当阻塞队列满时,再往队列里add插入元素会抛出IllegalStateException:Queue fll;当阻塞队列空时,再往队列里remove移除元素会抛出NoSuchElementExeception
特殊值:插入方法,成功true,失败false;移除方法,成功返回队列的元素,队列里没有就返回null
阻塞:当阻塞队列满时,线程往队列里put元素,队列会一直阻塞直到线程能put数据;当阻塞队列空时,线程从队列take元素,队列会一直阻塞直到可take元素
超时退出:当阻塞队列满时,队列会阻塞线程一定时间,超过限时后线程会退出
三、种类
ArrayBlockingQueue:由数组结构组成的有界阻塞队列
LinkedBlockingQueue:由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队列
PriorityBlockingQueue:支持优先级排序的无界阻塞队列
DelayQueue:使用优先级队列实现的延迟无界阻塞队列
SynchronousQueue:不存储元素的阻塞队列,也即单个元素的队列
LinkedTransferQueue:由链表结构组成的无界阻塞队列
LinkedBlockingDeque:由链表结构组成的双向阻塞队列
四、使用SynchronousQueue
SynchronousQueue是单个元素队列
生产线程put一个对象时,再put就会阻塞;消费者take一个对象后,再take就会阻塞
public class SynchronousQueueTest {
public static void main(String[] args) {
BlockingQueue<String> queue = new SynchronousQueue<>();
new Thread(()->{
try {
System.out.println(Thread.currentThread().getName() + "\t put 1");
queue.put("1");
System.out.println(Thread.currentThread().getName() + "\t put 2");
queue.put("2");
System.out.println(Thread.currentThread().getName() + "\t put 3");
queue.put("3");
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "生产").start();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "\t take " + queue.take());
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "\t take " + queue.take());
TimeUnit.SECONDS.sleep(1);
System.out.println(Thread.currentThread().getName() + "\t take " + queue.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "消费").start();
}
}