目录
阻塞队列
是特殊的队列
①线程安全
②带有阻塞特性
a.如果队列为空,继续出队列,就会发生阻塞,阻塞到其他线程往队列里添加元素为止
b.如果队列为满,继续入队列,也会发生阻塞,阻塞到其他线程从队列里取走元素为止
阻塞队列的最大意义,用来实现”生产者消费者“模型
生产者消费者模型意义
1.解耦合
比如,考虑一个简单的分布式系统
相比之下,使用生产者消费者模型就可以解决上述耦合问题
2.削峰填谷
(峰:请求量比较多 谷:请求量比较少)
引入生产者消费者模型后
java标准库中,已经提供了现成的阻塞队列
针对BlockingQueue提供了两种实现方式
1.基于数组
2.基于链表
public interface BlockingQueue<E> extends Queue<E>{}
put入阻塞队列
take出阻塞队列
如何自己实现阻塞队列?
一个普通队列+线程安全+阻塞
普通环形队列(这里采用设一个size记录长度的方式):
public void put(String elem){
if(size==data.length){
return;
}
data[tail]=elem;
tail++;
if(tail==data.length){
tail=0;
}
size++;
}
public String take(){
if(size==0){
return null;
}
String ret=data[head];
head++;
if(head==data.length){
head=0;
}
size--;
return ret;
}
实现阻塞队列:
public void put(String elem) throws InterruptedException {
if(size==data.length){
//如果队列满 阻塞等待 直到有元素take
this.wait();
return;
}
data[tail]=elem;
tail++;
if(tail==data.length){
tail=0;
}
size++;
//put后 队列中有元素了 释放take中的wait(如果有的话)
this.notify();
}
public String take() throws InterruptedException {
if(size==0){
//如果队列空 阻塞等待 直到有元素put
this.wait();
return null;
}
String ret=data[head];
head++;
if(head==data.length){
head=0;
}
size--;
//take后 队列中不满了,释放put中的wait(如果有的话)
this.notify();
return ret;
}
if(size==data.length){
try{
this.wait();
}catch(InterruptedException e){
}
}
如果代码这样写,出现异常后方法不会结束,会继续往下执行,会出现bug
public void put(String elem) throws InterruptedException
而采用这种方法,出现异常后,方法会结束,不会出现bug
所以,加一个判断条件,wait唤醒后再确认一次队列满不满,如果队列还是满的,继续wait)
后续的代码中,有的要进行读(判定),有的要进行写(修改),为了避免内存可见性问题,加上volatile
阻塞队列最终版本
public class BlockingQueue {
private String[] data = new String[1000];
private volatile int head = 0;
// 队列的结束位置的下一个位置.
private volatile int tail = 0;
// 队列中有效元素的个数.
private volatile int size = 0;
public void put(String elem) throws InterruptedException {
if(size==data.length){
//如果队列满 阻塞等待 直到有元素take
this.wait();
return;
}
data[tail]=elem;
tail++;
if(tail==data.length){
tail=0;
}
size++;
//put后 队列中有元素了 释放take中的wait(如果有的话)
this.notify();
}
public String take() throws InterruptedException {
if(size==0){
//如果队列空 阻塞等待 直到有元素put
this.wait();
return null;
}
String ret=data[head];
head++;
if(head==data.length){
head=0;
}
size--;
//take后 队列中不满了,释放put中的wait(如果有的话)
this.notify();
return ret;
}
}