阻塞队列的创建
public void put(int value) throws InterruptedException {
//加锁防止线程安全问题,保证原子性
synchronized(this){
//使用while循环是因为:interrupt也能唤醒wait,while循环能再确认一遍是否是可以再添加元素
while(size >= items.length){
this.wait();
}
//在队列的最后位置添加元素
items[tail] = value;
//可以用这种方式,也能用取模的方式
tail++;
if(tail >= items.length){
tail = 0;
}
// tail = (tail +1)%items.length;
this.notify();
size++;
}
}
public int take() throws InterruptedException {
//加锁防止线程安全问题:
synchronized(this){
while(size == 0){
this.wait();
}
int ret = items[head];
head++;
if(head >= items.length){
head = 0;
}
size--;
//等取出一个元素后,队列就不是满的了,所以能唤醒其他线程了,但是最好不要用notifyAll
this.notify();
return ret;
}
}
我们可以参考一下源码:
唤醒的基本逻辑:
使用 if 和while的区别:
不用notifyAll的原因:
主要是针对try-catch
- 由于我们在使用throws InterruptedException之后只要是interrupt 使wait唤醒,那么就会抛出异常(来自于异常那一节的知识点),方法就直接结束了,不会再往下走了。所以,我们加上while主要是针对try-catch这样的,其实两种情况都能加,加上while会更安全。
public void put(int value) {
synchronized(this){
while(size >= items.length){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
items[tail] = value;
tail++;
if(tail >= items.length){
tail = 0;
}
this.notify();
size++;
}
}
public int take() {
while(size == 0){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
int ret = items[head];
head++;
if(head >= items.length){
head = 0;
}
size--;
this.notify();
return ret;
}
}