如何實現生產者消費者模型?
- 簡單來說就是使用阻塞隊列來實現該模型
- 阻塞隊列的實現:
- 阻塞隊列依舊是一個先進先出的隊列
- 入隊列時如果發現隊列滿了,就會阻塞,直到其他線程調用出隊列操讓隊列有空位之後 ,才能繼續入隊列
- 出隊列的時候如果發現隊列爲空,也會阻塞, 直到其他線程調用入隊列操作rag隊列有元素,才能繼續出隊列
實現阻塞隊列
//阻塞隊列
public class BlockingQueue {
private int[] array = new int[20];
private int haed = 0;
private int tail = 0;
private volatile int size = 0;
//put向隊列放元素
public void put(int val) throws InterruptedException {
synchronized (this) {
while (this.size == array.length) {
this.wait();
}
array[tail] = val;
tail++;
size++;
if (tail == array.length) {
this.tail = 0;
}
this.notify();
}
}
//take取隊首元素
public int take() throws InterruptedException {
int ret;
synchronized (this) {
while (this.size == 0) {
this.wait();
}
ret = array[haed];
haed++;
size--;
if (haed == array.length) {
this.haed = 0;
}
this.notify();
}
return ret;
}
}
代碼分析
- 詳細說一下爲什麼判斷空或者滿要使用while而不是使用if
假設現在又三個線程 一個生產 倆個消費
而且是消費快 生產慢
此時倆個消費都會判斷爲空然後進入wait
如果此時我們不小心使用了notiAll喚醒了所有等待的線程
於是消費者1先得到鎖 執行了出隊列操作 生產者還沒來得及生產 消費者2就又獲取了鎖 此時剛剛生產了一個元素已經被消費者拿走了 當前已經是一個空隊列了
如果再往下執行就會發生邏輯錯誤 結果就不可控了 - 所以我們在判斷條件進行使用wait的時候 都推薦使用while去搭配而不是if