Java設計模式 - 生產者、消費者

     對於多線程程序來講,無論任何編程語言,生產者和消費者模型都是最經典的。就像學習每一門編程語言同樣,Hello World!都是最經典的例子。java

     實際上,準確說應該是「生產者-消費者-倉儲」模型,離開了倉儲,生產者消費者模型就顯得沒有說服力了。編程

     對於此模型,應該明確一下幾點:多線程

一、生產者僅僅在倉儲未滿時候生產,倉滿則中止生產。編程語言

二、消費者僅僅在倉儲有產品時候才能消費,倉空則等待。ide

三、當消費者發現倉儲沒產品可消費時候會通知生產者生產。學習

四、生產者在生產出可消費產品時候,應該通知等待的消費者去消費。this

 

     此模型將要結合java.lang.Object的wait與notify、notifyAll方法來實現以上的需求。這是很是重要的。 線程

     注意:1.用while判斷而不用if,由於while能保證在等待中的線程被喚醒後可以先進行while判斷,若是是if則再也不判斷,會致使錯誤。code

               2.用notifyAll而不用notify,由於notify僅通知相同類型的線程,這時,若是該類型線程處於等待則整個程序會產生死鎖;若是使用notifyAll則通知了全部線程,這樣總能有線程繼續運行下去,程序不會產生死鎖。blog

/**
 *
 * @author Yuanyuan
 */
public class TestCP
{
    public static void main(String[] args)
    {
        Base b = new Base(20);
        Customer1 c1 = new Customer1(b, 10);
        Customer1 c2 = new Customer1(b,20);   
        Customer1 c3 = new Customer1(b,20);   
        Producer1 p1 = new Producer1(b, 10);
        c1.start();
        c2.start();
        c3.start();
        p1.start();
    }
}
  
    
   class Base
   {
       private static final int total = 100;
       private int current;
       public Base(int initSize)
       {
           this.current = initSize;
       }
       public Base()
       {
       }
       public synchronized void produce(int size)
       {
           while (size > total - current)
           {
               System.out.println("要生產的產品量" + size + "超出了倉庫剩餘容量" + (total - current) + ",暫時沒法生產!");
               try
               {
                   this.wait();
               } catch (Exception ex)
               {
                   System.out.println(ex.getMessage());
                   ex.printStackTrace();
               }
           }
           current = current + size;
           System.out.println("新生產了" + size + ",當前庫存" + current);
           this.notifyAll();
       }
       public synchronized void custum(int size)
       {
           while (size > current)
           {
               System.out.println("要消費的產品量" + size + "超出了庫存" + current + ",暫時沒法消費!");
               try
               {
                   this.wait();
               } catch (Exception ex)
               {
                   System.out.println(ex.getMessage());
                   ex.printStackTrace();
               }
           }
           current = current -size;
           System.out.println("新消費了"+size+"當前庫存"+current);
           this.notifyAll();
       }
       
   }
   
   class Producer1 extends Thread
   {
       private Base b;
       private int size;
       public Producer1(Base b,int size)
       {
           this.b = b;
           this.size = size;
       }
       @Override
        public void run()
        {
            b.produce(size);
        }
    }
    
    class Customer1 extends Thread
    {
        private Base b;
        private int size;
        public Customer1(Base b, int size)
        {
            this.b = b;
            this.size = size;
        }
        @Override
        public void run()
        {
            b.custum(size);
        }
    }

運行結果:

新消費了10當前庫存10

新生產了10,當前庫存20

新消費了20當前庫存0

要消費的產品量20超出了庫存0,暫時沒法消費!

參考資料:http://lavasoft.blog.51cto.com/62575/221932/

相關文章
相關標籤/搜索