Liver's Java
          我不夠貪心!其實(shí)我應(yīng)該明白,心有多貪,舞臺(tái)就會(huì)有多大!堅(jiān)持!奮斗!
          posts - 4,  comments - 6,  trackbacks - 0
          昨天提到了線程,那么就不得不提到“生產(chǎn)者與消費(fèi)者”這樣一個(gè)經(jīng)典的線程同步問(wèn)題

          場(chǎng)景描述:
              一個(gè)倉(cāng)庫(kù),生產(chǎn)者在工廠里生產(chǎn)了產(chǎn)品后,將產(chǎn)品存放到倉(cāng)庫(kù)里,倉(cāng)庫(kù)存放數(shù)量有限,當(dāng)滿倉(cāng)后,停止生產(chǎn),直到有消費(fèi)著將產(chǎn)品消費(fèi)后才繼續(xù)生產(chǎn);消費(fèi)者從倉(cāng)庫(kù)里提取產(chǎn)品,當(dāng)倉(cāng)庫(kù)空倉(cāng)時(shí),停止消費(fèi)產(chǎn)品,直到倉(cāng)庫(kù)中有產(chǎn)品時(shí),才繼續(xù)消費(fèi)產(chǎn)品。

          代碼的實(shí)現(xiàn)(調(diào)整線程sleep時(shí)間可以實(shí)現(xiàn)生產(chǎn)速度與消費(fèi)速度的不同):
          TestProduceAndConsumer.java
          package com.nantian;

          import java.util.Random;

          public class TestProduceAndConsumer {
              
          public static void main(String[] args) {
                  
          // 創(chuàng)建一個(gè)工廠對(duì)象
                  ProductFactory pf = new ProductFactory();
                  
          // 創(chuàng)建一個(gè)生產(chǎn)者和一個(gè)消費(fèi)者,傳遞工廠的引用,保證兩者操作的是同一個(gè)工廠
                  Producer p = new Producer(pf);
                  Consumer c 
          = new Consumer(pf);
                  
          // 啟動(dòng)兩個(gè)線程
                  p.start();
                  c.start();
              }

          }


          // 產(chǎn)品工廠
          class ProductFactory {
              
          // product表示倉(cāng)庫(kù)
              private char[] product = ' '' '' '' '' '};
              
          // flag標(biāo)記產(chǎn)品數(shù)量
              private int flag = 0;

              
          // 生產(chǎn)產(chǎn)品
              public synchronized void produceProduct(char p) throws InterruptedException {
                  
          // 判斷產(chǎn)品是否滿倉(cāng),以便決定是否繼續(xù)生產(chǎn)
                  if (flag == product.length) {
                      
          this.wait();
                  }

                  
          // 當(dāng)代碼執(zhí)行到這里,一定不是滿倉(cāng)狀態(tài)
                  product[flag++= p;
                  
          // 查看此時(shí)倉(cāng)庫(kù)狀態(tài)(這里不屬于業(yè)務(wù)邏輯部分)
                  System.out.print(p + "被生產(chǎn),當(dāng)前倉(cāng)庫(kù)狀態(tài):");
                  
          for (char tmp : product) {
                      System.out.print(tmp);
                  }

                  System.out.println();
                  
          // 生產(chǎn)方法完成,如果存在等待隊(duì)列中的線程,應(yīng)該喚醒
                  this.notifyAll();
              }

              
              
          // 消費(fèi)產(chǎn)品
              public synchronized char consumeProduct() throws InterruptedException {
                  
          // 判斷倉(cāng)庫(kù)是否空倉(cāng),以便決定是否消費(fèi)產(chǎn)品
                  if(flag == 0{
                      
          this.wait();
                  }

                  
          // 當(dāng)代碼執(zhí)行到這里,一定不是空倉(cāng)狀態(tài)
                  char p = product[--flag]; product[flag]=' ';
                  
          // 查看此時(shí)倉(cāng)庫(kù)狀態(tài)(這里不屬于業(yè)務(wù)邏輯部分)
                  System.out.print(p + "被消費(fèi),當(dāng)前倉(cāng)庫(kù)狀態(tài):");
                  
          for(char tmp : product) {
                      System.out.print(tmp);
                  }

                  System.out.println();
                  
          // 消費(fèi)方法完成,如果存在等待隊(duì)列中的線程,應(yīng)該喚醒
                  this.notifyAll();
                  
          return p;
              }

          }


          // 生產(chǎn)者
          class Producer extends Thread {
              
          private ProductFactory pf = null;
              
              
          public Producer(ProductFactory pf) {
                  
          this.pf = pf;
              }

              
              
          public void run() {
                  
          // 一共生產(chǎn)20個(gè)產(chǎn)品
                  for(int i=0; i<20; i++{
                      
          // 隨機(jī)產(chǎn)生一個(gè)大寫字母作為產(chǎn)品
                      Random r = new Random();
                      
          char p = (char)(r.nextInt(26+ 'A');
                      
          try {
                          
          // 產(chǎn)品入庫(kù)
                          pf.produceProduct(p);
                          
          // 故意sleep,以便消費(fèi)線程有機(jī)會(huì)獲得CPU時(shí)間片,方便演示
                          Thread.sleep(200);
                      }
           catch (InterruptedException e) {
                          e.printStackTrace();
                      }

                  }

              }

          }


          // 消費(fèi)者
          class Consumer extends Thread {
              
          private ProductFactory pf = null;
              
              
          public Consumer(ProductFactory pf) {
                  
          this.pf = pf;
              }

              
              
          public void run() {
                  
          // 一共消費(fèi)20個(gè)產(chǎn)品
                  for(int i=0; i<20; i++{
                      
          try {
                          
          // 產(chǎn)品出庫(kù)
                          pf.consumeProduct();
                          
          // 故意sleep,以便生產(chǎn)線程有機(jī)會(huì)獲得CPU時(shí)間片,方便演示
                          
          // sleep時(shí)間稍微錯(cuò)開,阻止同時(shí)競(jìng)爭(zhēng)CPU時(shí)間片
                          Thread.sleep(300);
                      }
           catch (InterruptedException e) {
                          e.printStackTrace();
                      }

                  }

              }

          }
          posted on 2009-06-04 10:57 Liver 閱讀(1430) 評(píng)論(4)  編輯  收藏 所屬分類: CoreJava

          FeedBack:
          # re: 再談線程:生產(chǎn)者與消費(fèi)者
          2009-06-04 16:22 | wuzhongxing
          利用jdk1.5的concurrent包里面的blockqueue,實(shí)現(xiàn)這種模式還是比較簡(jiǎn)單的  回復(fù)  更多評(píng)論
            
          # re: 再談線程:生產(chǎn)者與消費(fèi)者
          2009-06-04 18:10 | 樂蜂
          實(shí)現(xiàn)這種模式還是比較簡(jiǎn)單的  回復(fù)  更多評(píng)論
            
          # re: 再談線程:生產(chǎn)者與消費(fèi)者[未登錄]
          2009-06-06 16:57 | charlee
          // 判斷產(chǎn)品是否滿倉(cāng),以便決定是否繼續(xù)生產(chǎn)
          if (flag == product.length) {
          this.wait();
          }

          // 判斷倉(cāng)庫(kù)是否空倉(cāng),以便決定是否消費(fèi)產(chǎn)品
          if(flag == 0) {
          this.wait();
          }

          為什么要用if呢?你不覺得while更好么?  回復(fù)  更多評(píng)論
            
          # re: 再談線程:生產(chǎn)者與消費(fèi)者
          2009-06-15 15:53 | 分享愛的空間
          言簡(jiǎn)意賅,不錯(cuò)。。。。
          希望看到更加深入的。  回復(fù)  更多評(píng)論
            

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


          網(wǎng)站導(dǎo)航:
           

          <2009年6月>
          31123456
          78910111213
          14151617181920
          21222324252627
          2829301234
          567891011

          常用鏈接

          留言簿

          隨筆分類(5)

          隨筆檔案(5)

          搜索

          •  

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 靖远县| 崇左市| 昌江| 天等县| 沾益县| 崇礼县| 彝良县| 万源市| 张北县| 庄浪县| 栖霞市| 兰西县| 南汇区| 陆良县| 日喀则市| 察隅县| 九寨沟县| 龙游县| 英山县| 襄垣县| 林甸县| 闽侯县| 沈丘县| 登封市| 芦溪县| 建瓯市| 库车县| 盈江县| 腾冲县| 四子王旗| 兴宁市| 鄂尔多斯市| 苏州市| 石家庄市| 安岳县| 睢宁县| 甘南县| 新津县| 香港 | 昭觉县| 山阴县|