Java多執行緒14 生產者 消費者模型

2021-09-07 02:54:37 字數 3652 閱讀 7028

什麼是生產者/消費者模型

一種重要的模型,基於等待/通知機制。生產者/消費者模型描述的是有一塊緩衝區作為倉庫,生產者可將產品放入倉庫,消費者可以從倉庫中取出產品,生產者/消費者模型關注的是以下幾個點:

生產者/模型作為一種重要的模型,它的優點在於:

利用wait()/notify()實現生產者/消費者模型

既然生產者/消費者模型有乙個緩衝區,那麼我們就自己做乙個緩衝區,生產者和消費者的通訊都是通過這個緩衝區的。value為""表示緩衝區空,value不為""表示緩衝區滿:

public

class

valueobject

接下來就是乙個生產者了,如果緩衝區滿了的,那麼就wait(),不再生產了,等待消費者消費完通知;如果緩衝區是空的,那麼就生產資料到緩衝區中

public

class

producer

public

void

setvalue()

}catch

(interruptedexception e)

}}

消費者類似,如果緩衝區是空的,那麼就不再消費,wait()等待,等待生產者生產完通知;如果緩衝區不是空的,那麼就去拿資料:

public

class

customer

public

void

getvalue()

} catch

(interruptedexception e)

}}

寫個主函式,開兩個執行緒呼叫producer裡面的getvalue()方法和customer()裡面的setvalue()方法:

public

static

void

main(string args)}};

runnable customerrunnable = new

runnable()}};

thread producerthread = new

thread(producerrunnable);

thread customerthread = new

thread(customerrunnable);

producerthread.start();

customerthread.start();

}

看一下執行結果:

...

set的值是:1444025677743_162366875965845

get的值是:1444025677743_162366875965845

set的值是:1444025677743_162366875983541

get的值是:1444025677743_162366875983541

set的值是:1444025677743_162366876004776

get的值是:1444025677743_162366876004776

...

生產資料和消費資料一定是成對出現的,生產乙個消費乙個,滿了不生產,空了不消費,生產者不能無限生產,消費者也不能無限消費,符合生產者/消費者模型。生產者速度快,就不占用cpu時間片,等著消費者消費完通知它繼續生產,這塊時間片可以用來給其他執行緒用。

利用await()/signal()實現生產者和消費者模型

一樣,先定義乙個緩衝區:

public

class

valueobject

換種寫法,生產和消費方法放在乙個類裡面:

public

class threaddomain41 extends

reentrantlock

catch

(interruptedexception e)

finally

}public

void

get()

catch

(interruptedexception e)

finally

}}

同樣的,開兩個執行緒,乙個執行緒呼叫set()方法生產,另乙個執行緒呼叫get()方法消費:

public

static

void

main(string args)

};runnable customerrunnable = new

runnable()

};thread producerthread = new

thread(producerrunnable);

producerthread.setname("producer");

thread consumerthread = new

thread(customerrunnable);

consumerthread.setname("consumer");

producerthread.start();

consumerthread.start();

}

看一下執行結果:

...

producer生產了value, value的當前值是123

consumer消費了value, value的當前值是

producer生產了value, value的當前值是123

consumer消費了value, value的當前值是

producer生產了value, value的當前值是123

consumer消費了value, value的當前值是

...

和wait()/notify()機制的實現效果一樣,同樣符合生產者/消費者模型

小心假死

生產者/消費者模型最終達到的目的是平衡生產者和消費者的處理能力,達到這個目的的過程中,並不要求只有乙個生產者和乙個消費者。可以多個生產者對應多個消費者,可以乙個生產者對應乙個消費者,可以多個生產者對應乙個消費者。

假死就發生在上面三種場景下。理論分析就能說明問題,所以就不寫**了。**要寫也很簡單,上面的兩個例子隨便修改乙個,開乙個生產者執行緒/多個消費者執行緒、開多個生產者執行緒/消費者執行緒、開多個生產者執行緒/多個消費者執行緒都可以。假死指的是全部執行緒都進入了waiting狀態,那麼程式就不再執行任何業務功能了,整個專案呈現停滯狀態。

比方說有生產者a和生產者b,緩衝區由於空了,消費者處於waiting。生產者b處於waiting,生產者a被消費者通知生產,生產者a生產出來的產品本應該通知消費者,結果通知了生產者b,生產者b被喚醒,發現緩衝區滿了,於是繼續waiting。至此,兩個生產者執行緒處於waiting,消費者處於waiting,系統假死。

上面的分析可以看出,假死出現的原因是因為notify的是同類,所以非單生產者/單消費者的場景,可以採取兩種方法解決這個問題:

1、synchronized用notifyall()喚醒所有執行緒、reentrantlock用signalall()喚醒所有執行緒

2、用reentrantlock定義兩個condition,乙個表示生產者的condition,乙個表示消費者的condition,喚醒的時候呼叫相應的condition的signal()方法就可以了

java多執行緒初探(零)生產者消費者模式 執行緒通訊

測試類 package gcc.twothreadtransdata.producerandconsumer import org.slf4j.logger import org.slf4j.logge ctory 多個執行緒之間通訊 消費者生產者模式 多個生產者和消費者 流程 多個執行緒 生產者,...

java多執行緒(生產者 消費者)

if isempty 當生產者生產出來商品需要喚醒消費者消費,可進行如下控制 vector.vector.notify 喚醒消費方法還用到了同步的方法,具體語法如下 synchronized vector.vector 程式源 如下 public class thread01 public stat...

執行緒(六) 生產者消費者模式

為什麼要使用生產者消費者模式 什麼是生產者消費者模式 生產者消費模式是通過乙個容器來解決生產者和消費者的強耦合問題。生產者和消費這彼此之間不直接通訊,而通過阻塞佇列來進行通訊,所以生產者生產完資料之後不用等待消費者處理,直接扔給阻塞佇列,消費者不找生產者要資料,而是直接從阻塞佇列就相當於乙個緩衝區,...