午夜拍鍵驚奇
          子夜 編程 代碼與我同在
          posts - 48,comments - 118,trackbacks - 79

          引子:
          大家上過操作系統的都知道“生產者-消費者(Producer-Consumer)”模型,主要討論的是進程(線程)間的互斥和同步問題,關鍵是對鎖(lock)的申請、獨占和釋放,在這里我就不羅嗦了。原先我寫的Java代碼如下:

          public class Producer extends Thread{
            
          private ProductList products = ProductList.getInstance();
            
            
          public void run(){
              
          int i = 0;
              
              
          while(i <= 20){
                
          synchronized(products)// Get lock on product list
              if(products.isFull()){
                System.out.println(
          "List is full");
                products.notify(); 
          // Release the lock
              }
           else{
                Product product 
          = new Product(i++); // Produce a product
                products.put(product);
                System.out.println(
          "Produced product " + product.getId());
                products.notify(); 
          // Release lock
              }

                }
           // Release the lock
              }

            }

          }

          public class Consumer extends Thread{
            ProductList products 
          = ProductList.getInstance();
            
            
          public void run(){
              
          while(true){
                
          synchronized(products){
              
          try {
                products.wait(); 
          // Wait for lock
                Product product = null;
                
          if(!(products.isEmpty()))
                  product 
          = products.take();
                
          else
                  System.out.println(
          "List is empty");
                System.out.println(
          "Consumed product " + product.getId()); // Get the lock
              }
           catch (InterruptedException ex) {
                ex.printStackTrace();
              }

                }
           // Release the lock
              }

            }

          }


          import java.util.ArrayList;
          import java.util.List;

          public class ProductList {
            
          private static ProductList instance = new ProductList();
            
          private List<Product> products; // Adapter pattern
            public static final int SIZE = 10;
            
            
          private ProductList() {
              products 
          = new ArrayList<Product>(SIZE);
            }

            
            
          public static ProductList getInstance() // Singleton pattern
              return instance;
            }

            
            
          public boolean isFull() {
              
          return products.size() == SIZE;
            }

            
            
          public void put(Product product) {
              products.add(product);
            }

            
            
          public Product take() {
              
          return products.remove(0);
            }

            
            
          public boolean isEmpty() {
              
          return products.isEmpty();
            }

          }


          public class Product {
            
          private int id;
            
            
          public Product(int id) {
              
          this.id = id;
            }

            
            
          public int getId() {
              
          return id;
            }

          }


          public class Main {
            
          public static void main(String[] args){
              Producer p 
          = new Producer();
              Consumer c 
          = new Consumer();
              
              p.start();
              c.start();
            }

          }


          雖然Java對信號量及原語做了更高層次的封裝(wait()、notify()、notifyAll()、synchronized{}),但看完上述代碼還是覺得有點麻煩,于是JDK 5在原先collection框架的基礎上增加了java.util.concurrent包,封裝了許多用于線程并發操作的數據結構和操作。其中的BlockingQueue接口就是封裝了一個阻塞隊列的接口,具體地說就是實現了一個用于消費者(多個)和生產者(多個)交換產品的中介,生產者線程在隊列滿時阻塞,消費者線程在隊列空時阻塞,當然在沒有得到鎖之前兩類線程均會阻塞。詳細信息可以參考Java Doc。下面用BlockingQueue實現P-C模型:

          class Producer implements Runnable {
             
          private final BlockingQueue queue;
             Producer(BlockingQueue q) 
          { queue = q; }
             
          public void run() {
               
          try {
                 
          while(true{ queue.put(produce()); }
               }
           catch (InterruptedException ex)  handle }
             }

             Object produce() 
           }
           }


           
          class Consumer implements Runnable {
             
          private final BlockingQueue queue;
             Consumer(BlockingQueue q) 
          { queue = q; }
             
          public void run() {
               
          try {
                 
          while(true{ consume(queue.take()); }
               }
           catch (InterruptedException ex)  handle }
             }

             
          void consume(Object x)  }
           }


           
          class Setup {
             
          void main() {
               BlockingQueue q 
          = new SomeQueueImplementation();
               Producer p 
          = new Producer(q);
               Consumer c1 
          = new Consumer(q);
               Consumer c2 
          = new Consumer(q);
               
          new Thread(p).start();
               
          new Thread(c1).start();
               
          new Thread(c2).start();
             }

           }


          可以看出代碼中沒有出現wait()或notify()之類的原語操作,這些操作由concurrent框架負責封裝。更全面的討論可以參考馴服 Tiger: 并發集合(IBM)
          posted on 2005-10-11 16:56 ^ Mustang ^ 閱讀(13669) 評論(1)  編輯  收藏 所屬分類: Java 點滴

          FeedBack:
          # 發現一個問題
          2011-09-11 11:48 | 劉sir
          你前半部分的消費者線程搞的有問題  回復  更多評論
            
          主站蜘蛛池模板: 盐亭县| 平阴县| 开江县| 莱西市| 神木县| 邢台市| 永安市| 新化县| 平舆县| 兴安县| 公主岭市| 仪征市| 扎鲁特旗| 汉阴县| 乐安县| 阿拉善盟| 深水埗区| 定安县| 手游| 平安县| 即墨市| 南投县| 葫芦岛市| 古浪县| 互助| 大悟县| 双流县| 清水河县| 漳平市| 湘潭县| 辽宁省| 奈曼旗| 赣榆县| 建湖县| 安福县| 休宁县| 石台县| 大名县| 南溪县| 旌德县| 玉门市|