生產者與消費者的實現

2021-10-04 07:13:19 字數 1948 閱讀 9392

一到多個執行緒充當生產者,生產元素。一到多個執行緒充當消費者,消費元素。在兩者之間插入乙個佇列充當緩衝區,建立起生產者和消費者的鬆散耦合。

正常情況下,即生產元素的速度和消費元素的速度差不多時,生產者和消費者其實是不需要去關注對方的。

生產者可以一直生產,因為佇列裡總是有空間。消費者可以一直消費,因為佇列裡總是有元素。即達到乙個動態的平衡。

但在特殊情況下,比如生產元素的速度很快,佇列裡沒有了空間,此時生產者必須自我「停工」,開始「休息」。

一旦消費者消費了元素之後,佇列裡才會有空間,生產者才可以重啟生產,所以,消費者在消費完元素後有義務去叫醒生產者復工。

更準確的說法應該是,只有在生產者「休息」時,消費者消費完元素後才需要去叫醒生產者。否則,其實可以不用叫醒,因為人家本來就沒休息。

反之,如果消費元素的速度很快,佇列裡沒有了元素,只需把上述情況顛倒過來即可。

但這樣的話就會引入乙個新的問題,就是要能夠準備的判斷出對方有沒有在休息,為此就必須定義乙個狀態變數,在自己即將開始休息時,自己設定下這個變數。

對方通過檢測這個變數,來決定是否進行叫醒操作。當自己被叫醒後,首先要做的就是清除一下這個變數,表明我已經醒來復工了。

這樣就需要多維護乙個變數和多了一部分判斷邏輯。可能有些人會覺得可以通過判斷佇列的「空」或「滿」(即佇列中的元素數目)來決定是否進行叫醒操作。

在高併發下,可能剛剛判斷佇列不為空,瞬間之後佇列可能已經變為空的了,這樣會導致邏輯出錯。執行緒可能永遠無法被叫醒。

因此,綜合所有,生產者每生產乙個元素後,都會通知消費者,「現在有元素的,你可以消費」。

同樣,消費者每消費乙個元素後,也會通知生產者,「現在有空間的,你可以生產」。

很明顯,這些通知很多時候(即對方沒有休息時)是沒有真正意義的,不過無所謂,只要忽略它們就行了。

首先要保證是正確的,「寧可錯殺一千,也不放過乙個」。

常見的生產者與消費者的實現有以下幾種:

下面以lock實現簡單生產者和消費者:

public static void main(string args) 

/***

* 生產者**/

static class producer implements runnable

@override

public void run()

} catch (exception e)

}} /**

** 消費者**/

static class consumer implements runnable

@override

public void run()

} catch (exception e)

}} /**

** 生產佇列**/

static class queue

container[putindex] = ele;

println("生產元素:%d", ele);

putindex++;

if (putindex >= capacity)

count++;

println("通知消費者去消費。。。");

conscond.signalall();

} finally

}public object takeele() throws interruptedexception

object ele = container[takeindex];

println("消費元素:%d", ele);

takeindex++;

if (takeindex >= capacity)

count--;

println("通知生產者去生產。。。");

prodcond.signalall();

return ele;

} finally

}}

生產者消費者 生產者與消費者模式

一 什麼是生產者與消費者模式 其實生產者與消費者模式就是乙個多執行緒併發協作的模式,在這個模式中呢,一部分執行緒被用於去生產資料,另一部分執行緒去處理資料,於是便有了形象的生產者與消費者了。而為了更好的優化生產者與消費者的關係,便設立乙個緩衝區,也就相當於乙個資料倉儲,當生產者生產資料時鎖住倉庫,不...

生產者與消費者

include include include include include include define size of buffer 10 int buffer size of buffer 緩衝陣列 int in 0,out 0 採用迴圈佇列方式進行陣列的訪問 宣告訊號量 sem t ful...

生產者與消費者

include include include include include include handle mutex 互斥訊號量 handle full 滿緩衝區訊號量計數 handle empty 空緩衝區訊號量計數 void producer 生產者函式 void consumer 消費者函...