阻塞队列
定义:顾名思义,首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下
当阻塞队列是空时,从队列中获取元素的操作会被阻塞。
当阻塞队列是满时,往队列里添加元素的操作将会被阻塞。
这个是消息队列的底层原理
优点:可以不用管阻塞或者唤醒,阻塞队列会解决,可以很简单的写出一个生产者消费者模式。
java实现类架构梳理
BlockingQueue是一个接口类,具体的实现类有以下7中:
ArrayBlockingQueue; 由数组结构组成的有界阻塞队列
LinkedBlockingDeque;由链表结构组成的有界(但大小默认值为Integer.MAX_VALUE)阻塞队列
PriorityBlockingQueue;支持优先级排序的无界阻塞队列
DelayQueue;使用优先级队列实现的延迟无阻塞队列
SynchronousQueue;不存储元素的阻塞队列,也即单个元素的队列
LinkedTransferQueue;由链表结构组成的无界阻塞队列。
LinkedBlocking==Deque ==;由链表结构组成的双向阻塞队列
具体使用方法
方法类型 | 抛出异常 | 特殊值 | 阻塞 | 超时 |
---|---|---|---|---|
插入 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除 | remove() | poll() | take() | poll(time,unit) |
检查 | element | peek | 不可用 | 不可用 |
1、就是抛异常的方法在插入满了之后,会报一个异常,remove一样,element是检查队头的元素或者是否为空。
2、特殊值的方法是在插入满之后返回值变成了false而不是一个异常,取出失败的时候返回null。
3、阻塞方法是在插入满之后把这个方法阻塞,一直等待队列空出来一个之后再进行加入,会出现一直等待,也可能出现饥饿现象。
4、超时方法的话,当阻塞队列满时,队列会阻塞生产者线程一定时间,超过限时后生产者线程会退出。
什么情况下应用?
- 生产者消费者模式
传统版的代码:
class ShareData{
//资源类
private int number = 0;
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void increment()throws Exception{
lock.lock();
try{
//1 判断
while (number!=0){
//等待不能生产
condition.await();
}
//干活
number++;
System.out.println(Thread.currentThread().getName()+"\t "+number);
//通知唤醒
condition.signalAll();
}catch(Exception e){
e.printStackTrace();
}finally{
lock.unlock();
}
}
public void decrement()throws Exception{
lock.lock();
try