生產者消費者問題是線程模型中的經典問題:生產者和消費者在同一時間段內共用同一存儲空間,生產者向空間裏生產數據,而消費者取走數據。java
這裏實現以下狀況的生產--消費模型:多線程
生產者不斷交替地生產兩組數據「姓名--1 --> 內容--1」,「姓名--2--> 內容--2」,消費者不斷交替地取得這兩組數據,這裏的「姓名--1」和「姓名--2」模擬爲數據的名稱,「內容--1 」和「內容--2 」模擬爲數據的內容。this
因爲本程序中牽扯到線程運行的不肯定性,所以可能會出現如下問題:線程
一、假設生產者線程剛向數據存儲空間添加了數據的名稱,尚未加入該信息的內容,程序就切換到了消費者線程,消費者線程將把信息的名稱和上一個信息的內容聯繫在一塊兒;code
二、生產者生產了若干次數據,消費者纔開始取數據,或者是,消費者取完一次數據後,還沒等生產者放入新的數據,又重複取出了已取過的數據。對象
問題1很明顯要靠同步來解決,問題2則須要線程間通訊,生產者線程放入數據後,通知消費者線程取出數據,消費者線程取出數據後,通知生產者線程生產數據,這裏用wait/notify機制來實現。blog
詳細的實現代碼以下:get
class Info{ // 定義信息類 private String name = "name";//定義name屬性,爲了與下面set的name屬性區別開 private String content = "content" ;// 定義content屬性,爲了與下面set的content屬性區別開 private boolean flag = true ; // 設置標誌位,初始時先生產 public synchronized void set(String name,String content){ while(!flag){ try{ super.wait() ; }catch(InterruptedException e){ e.printStackTrace() ; } } this.setName(name) ; // 設置名稱 try{ Thread.sleep(300) ; }catch(InterruptedException e){ e.printStackTrace() ; } this.setContent(content) ; // 設置內容 flag = false ; // 改變標誌位,表示能夠取走 super.notify(); } public synchronized void get(){ while(flag){ try{ super.wait() ; }catch(InterruptedException e){ e.printStackTrace() ; } } try{ Thread.sleep(300) ; }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println(this.getName() + " --> " + this.getContent()) ; flag = true ; // 改變標誌位,表示能夠生產 super.notify(); } public void setName(String name){ this.name = name ; } public void setContent(String content){ this.content = content ; } public String getName(){ return this.name ; } public String getContent(){ return this.content ; } } class Producer implements Runnable{ // 經過Runnable實現多線程 private Info info = null ; // 保存Info引用 public Producer(Info info){ this.info = info ; } public void run(){ boolean flag = true ; // 定義標記位 for(int i=0;i<10;i++){ if(flag){ this.info.set("姓名--1","內容--1") ; // 設置名稱 flag = false ; }else{ this.info.set("姓名--2","內容--2") ; // 設置名稱 flag = true ; } } } } class Consumer implements Runnable{ private Info info = null ; public Consumer(Info info){ this.info = info ; } public void run(){ for(int i=0;i<10;i++){ this.info.get() ; } } } public class ThreadCaseDemo03{ public static void main(String args[]){ Info info = new Info(); // 實例化Info對象 Producer pro = new Producer(info) ; // 生產者 Consumer con = new Consumer(info) ; // 消費者 new Thread(pro).start() ; //啓動了生產者線程後,再啓動消費者線程 try{ Thread.sleep(500) ; }catch(InterruptedException e){ e.printStackTrace() ; } new Thread(con).start() ; } }
執行結果以下:同步
另外,在run方法中,兩者循環的次數要相同,不然,當一方的循環結束時,另外一方的循環依然繼續,它會阻塞在wait()方法處,而等不到對方的notify通知。it