posts - 14,  comments - 7,  trackbacks - 0
                 今天我們用實(shí)例程序說一下java中常見的生產(chǎn)者與消費(fèi)者的問題。

           首先看一下里面線程間的通信問題:


             一個(gè)線程向數(shù)據(jù)存儲(chǔ)空間添加數(shù)據(jù)(生產(chǎn)者),另一個(gè)線程從數(shù)據(jù)存儲(chǔ)空間去出數(shù)據(jù)(消費(fèi)者)。

          這個(gè)程序中有兩個(gè)可能出現(xiàn)的問題需要考慮:

          1、         假設(shè)生產(chǎn)者線程剛向數(shù)據(jù)存儲(chǔ)空間添加了一個(gè)食品的名字,還沒有加入這個(gè)食品的屬性,CPU就切換到了消費(fèi)者線程,消費(fèi)者線程將把這個(gè)食品的名字和這個(gè)人的屬性聯(lián)系在一起。

          2、         消費(fèi)者拿東西都希望自己拿到的是最新的,即生產(chǎn)者剛生產(chǎn)出,消費(fèi)者就拿走,而不是拿一些陳舊的。可能出現(xiàn)消費(fèi)者拿不了最新的在程序中的原因,生產(chǎn)者放了若干次的數(shù)據(jù),消費(fèi)者才開始取數(shù)據(jù),或者是,消費(fèi)者取完一個(gè)數(shù)據(jù)后,還沒等到生產(chǎn)者放入新的數(shù)據(jù),即消費(fèi)者比生產(chǎn)者快時(shí),又重復(fù)取出這個(gè)數(shù)據(jù)

              下面我們看一下具體的代碼,來體驗(yàn)一下生產(chǎn)者與消費(fèi)者的關(guān)系,平我們?nèi)コ喳湲?dāng)勞時(shí),總會(huì)要點(diǎn)吃的喝的,比如我們吃個(gè)漢堡喝個(gè)咖啡,而且這些都要是最新的,都是他們現(xiàn)做的。

          package com.dr.blog;

          class M{
              String name 
          = "Hamberger";
              String proper
          ="吃的";
              
          boolean flag = false;
          }

          class Pro implements Runnable{
              M m 
          = null;
              
          public Pro(M m){
                  
          this.m=m;
              }

              
          public void run(){
                  
          int i = 0;
                  
          while(true){
                      
          if(i==0){
                          m.name
          ="Hamberger";
                          m.proper
          ="吃的";
                          i
          =1;
                      }
          else{
                          m.name
          ="cofe";
                          m.proper
          ="喝的";
                          i
          =0;
                      }

                  }

              }

          }

          class Cus implements Runnable{
              M m 
          = null;
              
          public Cus(M m){
                  
          this.m= m;
              }

              
          public void run(){
                  
          while(true){
                      
          try {
                          Thread.sleep(
          100);
                      }
           catch (InterruptedException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }

                      System.out.println(m.name
          +"----->"+m.proper);
                      
                  }

              }

          }

          public class ThreadDemo02{
              
          public static void main(String[] args){
                  M m 
          = new M();
                  Pro p 
          = new Pro(m);
                  Cus c 
          = new Cus(m);
                  
          new Thread(p).start();
                  
          new Thread(c).start();
              }

          }

          運(yùn)行結(jié)果如下:

          可以看出這里出現(xiàn)了漢堡是喝的,咖啡是吃的的情況,也就是上面我們說的第一種情況,這個(gè)可以通過synchronized實(shí)現(xiàn)同步來解決,因?yàn)橘Y源共享需要同步。
          package com.dr.blog;

          class M1 {
              String name 
          = "Hamberger";
              String proper 
          = "吃的";
              
          //boolean flag = false;

              
          public synchronized void set(String name,String proper){
                  
          //if(!flag){
                      this.name= name;
                      
          this.proper=proper;
                      
          //flag = false;
                  
          //}
              }

               
          public synchronized void get(){
                  
          //if(flag){
                      System.out.println(this.name+"----->"+this.proper);
                      
          //flag = true;
                      
          //        }
                          }

              
          }


          class Pro1 implements Runnable {
              M1 m 
          = null;

              
          public Pro1(M1 m) {
                  
          this.m = m;
              }


              
          public void run() {
                  
          int i = 0;
                  
          while (true{
                      
          if (i == 0{
          //                m.name = "Hamberger";
          //                m.proper = "吃的";
                          m.set("Hamberger""吃的");
                          i 
          = 1;
                      }
           else {
          //                m.name = "cofe";
          //                m.proper = "喝的";
                          m.set("cofe""喝的");
                          i 
          = 0;
                      }

                  }

              }

          }


          class Cus1 implements Runnable {
              M1 m 
          = null;

              
          public Cus1(M1 m) {
                  
          this.m = m;
              }


              
          public void run() {
                  
          while (true{
                      
          try {
                          Thread.sleep(
          100);
                      }
           catch (InterruptedException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }

                      m.get();
                      
          //System.out.println(m.name + "----->" + m.proper);
                  }

              }

          }


          public class ThreadDemo01 {

              
          public static void main(String[] args) {
                  M1 m 
          = new M1();
                  Pro1 p 
          = new Pro1(m);
                  Cus1 c 
          = new Cus1(m);
                  
          new Thread(p).start();
                  
          new Thread(c).start();
              }


          }



           

          第一個(gè)問題已經(jīng)解決啦,但第二個(gè)問題還是存在,這個(gè)問題我們可以用線程的等待喚醒機(jī)制即wait(),notify()方法來解決

          Wait()告訴當(dāng)前線程放棄監(jiān)視器并進(jìn)入睡眠狀態(tài),直到其他線程進(jìn)入同一監(jiān)視器并調(diào)用notify()為止

          Notify()喚醒同一對(duì)象監(jiān)視器中調(diào)用wait()的第一線程


          package com.dr.blog;

          //package com.dr.blog;

          class M2 {
              String name 
          = "Hamberger";
              String proper 
          = "吃的";
              
          boolean flag = false;

              
          public synchronized void set(String name,String proper){
                  
          if(!flag){
                      
          try{
                          wait();
                      }
          catch(InterruptedException e){
                          e.printStackTrace();
                      }

                      
          this.name= name;
                      
          this.proper=proper;
                      flag 
          = false;
                      notify();
                  }

              }

               
          public synchronized void get(){
                  
          if(flag){
                      
          try {
                          wait();
                      }
           catch (InterruptedException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }

                      System.out.println(
          this.name+"----->"+this.proper);
                      flag 
          = true;
                      notify();
                              }

                          }

              
          }


          class Pro2 implements Runnable {
              M2 m 
          = null;

              
          public Pro2(M2 m) {
                  
          this.m = m;
              }


              
          public void run() {
                  
          int i = 0;
                  
          while (true{
                      
          if (i == 0{
          //                m.name = "Hamberger";
          //                m.proper = "吃的";
                          m.set("Hamberger""吃的");
                          i 
          = 1;
                      }
           else {
          //                m.name = "cofe";
          //                m.proper = "喝的";
                          m.set("cofe""喝的");
                          i 
          = 0;
                      }

                  }

              }

          }


          class Cus2 implements Runnable {
              M2 m 
          = null;

              
          public Cus2(M2 m) {
                  
          this.m = m;
              }


              
          public void run() {
                  
          while (true{
                      
          try {
                          Thread.sleep(
          100);
                      }
           catch (InterruptedException e) {
                          
          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }

                      m.get();
                      
          //System.out.println(m.name + "----->" + m.proper);
                  }

              }

          }


          public class ThreadDemo03 {

              
          public static void main(String[] args) {
                  M2 m 
          = new M2();
                  Pro2 p 
          = new Pro2(m);
                  Cus2 c 
          = new Cus2(m);
                  
          new Thread(p).start();
                  
          new Thread(c).start();
              }


          }



          現(xiàn)在我們開始說的兩個(gè)問題已經(jīng)解決啦!!
          posted on 2010-11-10 23:07 迷人笑笑 閱讀(2162) 評(píng)論(1)  編輯  收藏

          FeedBack:
          # re: java中消費(fèi)者與生產(chǎn)者的問題實(shí)例解析
          2010-12-14 17:17 | aben
          樓主有沒有搞錯(cuò)啊 你的最后那個(gè)截圖后面不還是亂的嗎 不是一個(gè)一個(gè)交替輸出的啊  回復(fù)  更多評(píng)論
            

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          <2010年12月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          常用鏈接

          留言簿(13)

          隨筆檔案

          文章檔案

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 游戏| 沐川县| 正阳县| 黎城县| 莒南县| 萍乡市| 南陵县| 武邑县| 孝昌县| 新平| 深州市| 武义县| 齐河县| 荆门市| 通江县| 积石山| 卓资县| 定兴县| 大宁县| 于都县| 轮台县| 黔西县| 洱源县| 三亚市| 确山县| 长治市| 剑阁县| 敦化市| 裕民县| 西平县| 哈巴河县| 江北区| 班玛县| 高安市| 年辖:市辖区| 邵阳县| 芒康县| 锦屏县| 新竹市| 锡林浩特市| 河池市|