一、普通不阻塞队列
还记得队列我们如何实现吗?我们用的是循环队列的方式,回一下:
描述:开始tail和head指针都指向最开始位置,往里面添加元素tail++,出元素head++
初始状态:
put元素后状态
take元素后状态
代码描述
public class MyBlockingQueue1 {
int size=0;//记录放了几个元素
int tail=0,head=0;
String []data=new String[3];
public void put(String elem){
if(size==data.length){
//队列满了
return;
}
data[tail++]=elem;
if(tail==data.length){
tail=0;
}
size++;
}
public String take(){
String sum;
if(size==0)return null;
sum=data[head++];
if(head==data.length)head=0;
size--;
return sum;
}
}
二、阻塞循环队列
这个阻塞的意思,我来解释下,就相当于,包饺子的时候,擀皮的人是生产者,包饺子的人是消费者,生产者每生产一个饺子,消费者就这一包饺子,如果生产者速度很慢,包饺子人手里没有了饺子皮,就会阻塞,当然如果消费者有很多的饺子皮,生产者进入阻塞
public class MyBlockingQueue2 {
int size=0;//记录放了几个元素
int tail=0,head=0;
String []data=new String[3];
Object locker=new Object();
public void put(String elem) throws InterruptedException {
//生产者
synchronized (locker){
while(size==data.length){//while是防止被特殊唤醒
//队列满了
//return;
locker.wait();
}
data[tail++]=elem;
if(tail==data.length){
tail=0;
}
size++;
locker.notify();//用来唤醒take的wait
}
}
//消费者
public String take() throws InterruptedException {
synchronized (locker){
String sum;
while (size==0)locker.wait();
sum=data[head++];
if(head==data.length)head=0;
size--;
locker.notify();//用来唤醒put中的wait
return sum;
}
}
}
class Test{
public static void main(String[] args) throws InterruptedException {
MyBlockingQueue2 queue=new MyBlockingQueue2();
//消费者
Thread t1=new Thread(()->{
while (true){
try {
String result=queue.take();
System.out.println("消费者元素"+result);
Thread.sleep(500);//让消费者慢点消费,很重要
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
//生产者
Thread t2=new Thread(()->{
int num=1;
while (true){
try {
queue.put(num+++"");
System.out.println("生产者元素"+num);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
});
t1.start();
t2.start();
}
}