posts - 297,  comments - 1618,  trackbacks - 0
                 這是以前為一師妹做的一機試題,雖后來因為她編程底子太弱,沒能獲得那份工作,拿在這里與大家共享之。
                 題目如下:
                在生產者/消費者模型中,生產者Producer負責生產數據,而消費者Consumer負責使用數據。多個生產者線程會在同一時間運行,生產數據,并放到內存中一個共享的區域。期間,多個消費者線程讀取內存共享區,消費里面的數據。
          要求:
               1. 針對上面的場景,請創建2個類,一個叫Producer,一個叫Consumer. 
               2. Producer類繼承Thread類,并實現把數據放到內存共享區的功能,這個功能要求是線程安全的。在個Producer類中的run方法中,循環20次,每次把一個整數放到內存共享區中。
               3. Consumer類也繼承Thread類,并實現在沒有沖突的情況下,從內存共享區中獲取數據,并在標準輸出設備中打印輸出。輸出的格式為:Consumer thread X retrieved integer Y.
               4. 最后,創建一個main class,創建10個Procuder線程和4個消費者線程并啟動這些線程。
               5. 要求有效代碼行數盡量少,最好不超過100行。
               我大概的做了一下,以下是我的代碼實現:
               一. 消費者類
               
          /**
           * 消費者類
           * 
          @author Amigo Xie(xiexingxing1121@126.com)
           *
           
          */

          class Consumer extends Thread 
              
          private Conn conn; 
              
          private int consumerNumber;
              
          public Consumer(Conn conn1, int conNum) 
                  conn 
          = conn1;
                  consumerNumber 
          = conNum;
              }

              
              
          public void run() 
                  
          for (int i = 0; i < 50; i++
                      System.out.println(
          "Consumer thread " +  consumerNumber + " retrieved integer: " + conn.read()); //
                      try 
                          sleep((
          int) (Math.random() * 2000)); 
                      }
           catch (InterruptedException e) {
                          e.printStackTrace();
                      }
           
                  }
           
              }

          }

              
                二. 生產者類
              
          /**
           * 生產者類
           * 
          @author Amigo Xie(xiexingxing1121@126.com)
           *
           
          */

          class Producer extends Thread 
              
          private Conn conn;

              
          public Producer(Conn conn1) 
                  conn 
          = conn1;
              }

              
              
          public void run() 
                  
          for (int i = 0; i < 20; i++
                      conn.add(i);
                  }
           
              }
           
          }

               
                 三. 線程通信類
          /**
           * 線程通信類
           * 
          @author Amigo Xie(xiexingxing1121@126.com)
           *
           
          */

          class Conn 
              
          private int buffer[] = new int[200]; //10個Procuder線程,需存放200個變量
              private int next = 0//Flags to keep track of our int buffer status 
              private boolean isFull = false
              
          private boolean isEmpty = true

              
          /**
               * method to read int
               * 
          @return
               
          */

              
          public synchronized int read() 
                  
          while (isEmpty == true//We can't read if there is nothing in our int buffer 
                      try 
                          wait();
          //we'll exit this when isEmpty turns false
                      }
          catch (InterruptedException e) {
                          e.printStackTrace();
                      }
           
                  }
           
                  
                  next
          --//decrement the count,since we're going to read one int 
                  if (next == 0
                      isEmpty 
          = true//Did we read the last letter? 
                  }

                  
                  isFull 
          = false;
                  notify();
                  
          return (buffer[next]);//return the int to the thread that is reading 
              }


              
          /**
               * method to add integer to the buffer
               * 
          @param number
               
          */

              
          public synchronized void add(int number) {  
                  
          while (isFull == true ) //Wait around until there's room to add another letter
                      try 
                          wait();
          //This will exit when isFull turns false 
                      }
          catch (InterruptedException e) {
                          e.printStackTrace();
                      }
           
                  }


                  next
          ++//add the integer to the next available spot buffer[next]=number;Change the next available spot 
                  if (next == 200
                      isFull 
          = true//Are we full?
                  }
           else {
                      buffer[next] 
          = number; 
                  }

                  isEmpty 
          =false
                  notify(); 
              }
           
          }


              四. 測試類
             
          /**
           * 測試類
           * 
          @author Amigo Xie(xiexingxing1121@126.com)
           *
           
          */

          public class ProducerAndConsumerTest {

              
          /**
               * 
          @param args
               
          */

              
          public static void main(String[] args) {
                  Conn conn 
          = new Conn();
                  Producer pro1 
          = new Producer(conn);
                  Producer pro2 
          = new Producer(conn);
                  Producer pro3 
          = new Producer(conn);
                  Producer pro4 
          = new Producer(conn);
                  Producer pro5 
          = new Producer(conn);
                  Producer pro6 
          = new Producer(conn);
                  Producer pro7 
          = new Producer(conn);
                  Producer pro8 
          = new Producer(conn);
                  Producer pro9 
          = new Producer(conn);
                  Producer pro10 
          = new Producer(conn);
                  
                  Consumer consumer1 
          = new Consumer(conn, 1);
                  Consumer consumer2 
          = new Consumer(conn, 2);
                  Consumer consumer3 
          = new Consumer(conn, 3);
                  Consumer consumer4 
          = new Consumer(conn, 4);
                  
                  pro1.start();
                  pro2.start();
                  pro3.start();
                  pro4.start();
                  pro5.start();
                  pro6.start();
                  pro7.start();
                  pro8.start();
                  pro9.start();
                  pro10.start();
                  
                  consumer1.start();
                  consumer2.start();
                  consumer3.start();
                  consumer4.start();
              }


          }


                  近來發現,去看以前的代碼,都覺得有點傻傻滴,現在的話如果去實現大抵會有所改進,我在進步中嗎?啊哈。
          posted on 2007-04-11 21:52 阿蜜果 閱讀(6294) 評論(8)  編輯  收藏 所屬分類: Java


          FeedBack:
          # re: 生產者/消費者模型模擬實現[未登錄]
          2007-04-11 23:01 | Tony
          樓主的測試類可不怎么幽雅,呵呵  回復  更多評論
            
          # re: 生產者/消費者模型模擬實現
          2007-04-11 23:15 | 阿蜜果
          @Tony
          啊哈,是極其不優雅,以前寫的代碼哩
          現在去看從前寫的代碼
          有時真想對它動動刀子。。。  回復  更多評論
            
          # re: 生產者/消費者模型模擬實現
          2007-04-12 10:28 | 劉甘泉
          哇,測試好多代碼~~~~~~~  回復  更多評論
            
          # re: 生產者/消費者模型模擬實現
          2007-04-13 09:19 | riverbuilding
          public synchronized void add
          public synchronized int read
          這兩個方法造成的結果是生產者生產時消費者不能同時消費,這個邏輯不多。  回復  更多評論
            
          # re: 生產者/消費者模型模擬實現
          2007-04-13 13:53 | hs
          樓上說的是,read方法的同步應該去掉。
          另外發表一下個人意見,供大家參考指正:
          以上的實現方法體現不出數據共享,或者說共享對象不明確。如果共享對象做成一個singleton,可能會好些,更能體現共享的含義。
          新建 一個對象,然后通過傳遞該對象到不同的生產者或消費者以達到共享對象,這種做法欠妥。這種做法導致邏輯不清析,同時可能會產生過期引用對象,當你認為該對象已經無用的時候,可能該對象還被引用著,導致不能回收,你也很難跟宗和控制這個對象。把共享對象做成singleton,使共享的邏輯清析,也明確該對象永遠存在。  回復  更多評論
            
          # re: 生產者/消費者模型模擬實現[未登錄]
          2007-04-13 14:14 | 阿蜜果
          @hs
          @riverbuilding
          :)
          感謝你們的建議
          這是以前寫的一程序
          打算抽空再重寫一次。  回復  更多評論
            
          # re: 生產者/消費者模型模擬實現
          2007-04-13 16:59 | att
          用 synchronizedList 代替你的那么通信類吧。  回復  更多評論
            
          # re: 生產者/消費者模型模擬實現
          2010-07-22 19:07 | Ilovesola
          看了你的幾篇文章,覺得還可以,所以多多關注了一下.

          能寫好生產-消費者的程序員不多.
          代碼我隨便看了一下 和評論也看了一下
          有人建議去 read同步方法, 這肯定不能去的,只能說明他們 對生產消費模弄理解不夠深.

          notify 建議換成 notifyAll();

          最后,說明下,不知道你測試過沒,你的程序貌似有個很嚴重的邏輯錯誤.

          就是 應該首先add/read 對象,然后再next++ ,next--

          我舉個例子,
          你執行 main方法 A線程 執行add方法 99次,然后B線程去read, 這時候 next=99,它就 read buffer[99] , 應該要read buffer[0]的
            回復  更多評論
            
          <2007年4月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

                生活將我們磨圓,是為了讓我們滾得更遠——“圓”來如此。
                我的作品:
                玩轉Axure RP  (2015年12月出版)
                

                Power Designer系統分析與建模實戰  (2015年7月出版)
                
               Struts2+Hibernate3+Spring2   (2010年5月出版)
               

          留言簿(263)

          隨筆分類

          隨筆檔案

          文章分類

          相冊

          關注blog

          積分與排名

          • 積分 - 2296331
          • 排名 - 3

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 洛宁县| 台北市| 连云港市| 凤山市| 四川省| 通化市| 德昌县| 行唐县| 长汀县| 江油市| 犍为县| 江达县| 涟源市| 韶关市| 襄城县| 桐柏县| 庆安县| 阳泉市| 白河县| 上林县| 丹阳市| 喀喇| 霞浦县| 尚义县| 茶陵县| 建阳市| 盐津县| 林甸县| 丹棱县| 英吉沙县| 马龙县| 凉城县| 乳山市| 三台县| 莎车县| 涞水县| 庐江县| 樟树市| 偃师市| 武平县| 台州市|