生產(chǎn)者消費者模型實現(xiàn)細節(jié)
生產(chǎn)者生產(chǎn)產(chǎn)品到公共倉庫释移,消費者消費公共倉庫中產(chǎn)品。
情況一:當公共倉庫產(chǎn)品達到倉庫容量上限辽狈,生產(chǎn)者停止生產(chǎn)慈参;
情況二:當公共倉庫沒有產(chǎn)品,或達到設(shè)置的倉庫容量下限刮萌,消費者停止消費驮配;
情況三:當公共倉庫產(chǎn)品達到容量上限時,消費者消費一次,就可以讓生產(chǎn)者繼續(xù)生產(chǎn)壮锻;
情況四:當公共倉庫沒有產(chǎn)品時琐旁,生產(chǎn)者生產(chǎn)一次,就可以讓消費者繼續(xù)消費猜绣;
功能實現(xiàn)說明
公共倉庫 灰殴,包含“倉庫容量上限”、“倉庫容量下限”掰邢、“當前容量”基礎(chǔ)屬性验懊,及“入庫”、“出庫”基礎(chǔ)方法尸变;
生產(chǎn)者 义图,包含“所屬倉庫”、“每次生產(chǎn)數(shù)量”基礎(chǔ)屬性召烂,及“生產(chǎn)存入倉庫”基礎(chǔ)方法碱工;
消費者 ,包含“所屬倉庫”奏夫、“每次消費數(shù)量”基礎(chǔ)屬性怕篷,及“倉庫取出消費”基礎(chǔ)方法;
代碼實現(xiàn)
公共倉庫 酗昼,抽取“入庫”廊谓、“出庫”基礎(chǔ)方法作為接口,后續(xù)可通過實現(xiàn)該接口麻削,重寫方法來實現(xiàn)蒸痹;
(1)公共倉庫接口
/** *@date2018年12月11日 *@methodputIn(int num) //往倉庫中存入指定數(shù)量的產(chǎn)品 *@methodoutOf(int num) //從倉庫中取出制定數(shù)量的產(chǎn)品 */interfaceAbstractStorage{voidputIn(intnum);voidoutOf(intnum);}
(2)倉庫實現(xiàn)類
倉庫類只需判斷庫存量是否達到存入/取出閾值,從而限制生產(chǎn)者/消費者的存入/取出呛哟,不需要使用循環(huán)來判斷叠荠;
/** *@date2018年12月11日 *@paramMAX_PRODUCT //倉庫容量上限 *@paramMIN_PRODUCT //倉庫容量下限 *@paramstock //倉庫當前容量,屬于共享資源 *@methodputIn(int) //當(庫存+即將存入)大于容量上限扫责,停止存入 *@methodoutOf(int) //當(庫存-即將取出)小于容量上限榛鼎,停止取出 */classStorageimplementsAbstractStorage{publicfinalintMAX_PRODUCT =10;publicfinalintMIN_PRODUCT =0;privateintstock;@OverridepublicsynchronizedvoidputIn(intnum){if((stock + num) >= MAX_PRODUCT) {System.out.println("庫存已滿!");try{wait();}catch(InterruptedException e) {e.printStackTrace();}}else{stock += num;System.out.println(Thread.currentThread().getName() +"存入鳖孤,庫存:"+ stock);notifyAll();}}@OverridepublicsynchronizedvoidoutOf(intnum){if((stock - num) <= MIN_PRODUCT) {System.out.println("庫存已空者娱!");try{wait();}catch(InterruptedException e) {e.printStackTrace();}}else{stock -= num;System.out.println(Thread.currentThread().getName() +"取出,庫存:"+ stock);notifyAll();}}publicintgetStock(){returnstock;}publicvoidsetStock(intstock){this.stock = stock;}}
生產(chǎn)者
使用實現(xiàn)Runnable接口方式創(chuàng)建生產(chǎn)者線程苏揣,將生產(chǎn)者生產(chǎn)操作放到重寫的run()方法中黄鳍,實現(xiàn)生產(chǎn)者線程生產(chǎn);
/** *@Data2018年12月11日 *@paramstorage //公共倉庫 *@paramnum //生產(chǎn)數(shù)量 *@constructorProduce(AbstractStorage) //構(gòu)造器 *@methodprod(int) //生產(chǎn)者生產(chǎn)方法 *@methodrun() //生產(chǎn)者線程執(zhí)行方法 *@methodsetNum(int) //設(shè)置生產(chǎn)者每次生產(chǎn)數(shù)量 */classProducerimplementsRunnable{privateAbstractStorage storage;privateintnum;publicProducer(AbstractStorage storage){this.storage = storage;}@Overridepublicvoidrun(){prod(num);}privatevoidprod(intnum){while(true) {try{Thread.sleep(100);//需要添加延時腿准,不然生產(chǎn)者線程獲得執(zhí)行權(quán)時际起,一瞬間即可生產(chǎn)到倉庫上限值}catch(InterruptedException e) {e.printStackTrace();}storage.putIn(num);}}publicvoidsetNum(intnum){this.num = num;}}
消費者
使用實現(xiàn)Runnable接口方式創(chuàng)建消費者線程,將消費者消費操作放到重寫的run()方法中吐葱,實現(xiàn)消費者線程消費街望;
/** *@Data2018年12月11日 *@paramstorage //公共倉庫 *@paramnum //生產(chǎn)數(shù)量 *@constructorConsume(AbstractStorage) //構(gòu)造器 *@methodcons(int) //消費者生產(chǎn)方法 *@methodrun() //消費者線程執(zhí)行方法 *@methodsetNum(int) //設(shè)置消費者每次生產(chǎn)數(shù)量 */classConsumerimplementsRunnable{privateAbstractStorage storage;privateintnum;publicConsumer(AbstractStorage storage){this.storage = storage;}@Overridepublicvoidrun(){cons(num);}privatevoidcons(intnum){while(true) {try{Thread.sleep(100);//需要添加延時,不然消費者線程獲得執(zhí)行權(quán)時弟跑,一瞬間即可消費到倉庫下限值}catch(InterruptedException e) {e.printStackTrace();}storage.outOf(num);}}publicvoidsetNum(intnum){this.num = num;}
測試類
/**
* @Date 2018年12月11日
* @param storage //創(chuàng)建公共倉庫
* @param producer //創(chuàng)建生產(chǎn)者線程
* @param consumer //創(chuàng)建消費者線程
*/public class TestA {public static void main(String[] args) {AbstractStorage storage = new Storage();Producer producer = new Producer(storage);Consumer consumer = new Consumer(storage);producer.setNum(2);consumer.setNum(1);Threadt1= new Thread(producer);Threadt2= new Thread(consumer);t1.setName("producer");t2.setName("consumer");t1.start();t2.start();}}
測試輸出
寫在最后的話
使用wait/notify方法實現(xiàn)灾前,很多時候會出現(xiàn)一些奇怪的問題,例如:
1孟辑、兩者都持有鎖且等待對方釋放鎖哎甲,造成死鎖的情況;
2饲嗽、對未持有鎖的對象進行釋放鎖炭玫,導致IllegalMonitorStateException異常;
3貌虾、加鎖時吞加,雙方所加的鎖并非同一把鎖,導致數(shù)據(jù)異常尽狠;
關(guān)于生產(chǎn)者/消費者模型衔憨,現(xiàn)在更多是使用阻塞隊列(Queue)的方式來實現(xiàn),后續(xù)會接著去學習那一塊知識袄膏。
【注】以上為本人通過網(wǎng)上視頻教程以及實例代碼整理所得践图,如果出錯以及更好的提議,歡迎留言指正沉馆,一起學習码党。
---------------------
每天都在分享文章,也每天都有人想要我出來給大家分享下怎么去學習Java斥黑。大家都知道闽瓢,我們是學Java全棧的,大家就肯定以為我有全套的Java系統(tǒng)教程心赶。沒錯扣讼,我是有Java全套系統(tǒng)教程,進扣裙【47】974【9726】所示缨叫,進群的時候記得表明自己想要學習什么椭符,不要用小號,這樣小編才好給你們發(fā)定向資源耻姥,今天小編就免費送!~
后記:對于大部分轉(zhuǎn)行的人來說销钝,找機會把自己的基礎(chǔ)知識補齊,邊工作邊補基礎(chǔ)知識琐簇,真心很重要蒸健∽恚“我們相信人人都可以成為一個程序員,現(xiàn)在開始似忧,找個師兄渣叛,帶你入門,學習的路上不再迷茫盯捌。這里是ja+va修真院淳衙,初學者轉(zhuǎn)行到互聯(lián)網(wǎng)行業(yè)的聚集地。"