浅谈wait和notify方法(生产者和消费者案例)

java.lang.Object类提供了wait()、notify()、notifyAll()方法,这些方法只有在synchronized或synchronized代码块中才能使用,是否就会报java.lang.IllegalMonitorStateException异常。 

当另外线程执行了某对象的notify方法之后,会唤醒在此对象等待池中的某个线程,使之成为可运行线程。notifyAll是唤醒在此对象等待池中所有的等待线程。 

下面我们来看看一个比较经典的问题:生产者/消费者问题 
问题描述如下: 
      生产者将产品交给店员,而消费者从店员处取走产品,店员一次只能持有固定数量的产品,如果生产者生产了过多的产品,店员会叫生产者等一下,如果店中有空位放产品了再通知;如果店中没有产品了,店员会告诉消费者等一下,如果店中有产品了再通知消费者来取产品。 

这里可能出现问题有以下两个: 
1. 生产者比消费者快时,消费者会漏掉一些数据没有取到 
2. 消费者比生产者快时,消费着会取相同的数据 

Java代码  收藏代码
  1. /** 
  2.  * 理解wait和notify方法 
  3.  * 生产者(Producer)/消费者(Consumer)问题 
  4.  * @author admin 
  5.  * 
  6.  */  
  7. public class ProductTest   
  8. {  
  9.   
  10.     /** 
  11.      * @param args 
  12.      */  
  13.     public static void main(String[] args)   
  14.     {  
  15.         Clerk clerk = new Clerk();  
  16.         Thread producerThread = new Thread(new Producer(clerk));  
  17.         Thread consumerThread = new Thread(new Consumer(clerk));  
  18.           
  19.         producerThread.start();  
  20.         consumerThread.start();  
  21.     }  
  22. }  
  23.   
  24. /** 
  25.  * 店员 
  26.  * @author admin 
  27.  * 
  28.  */  
  29. class Clerk   
  30. {  
  31.     //最大产品数  
  32.     private static final int MAX_PRODUCT = 20;  
  33.       
  34.     //最小产品数  
  35.     private static final int MIN_PRODUCT = 0;  
  36.       
  37.     //默认为0个产品  
  38.     private int product = 0;  
  39.       
  40.       
  41.     /** 
  42.      * 生产者生产出来的产品交给店员 
  43.      */  
  44.     public synchronized void addProduect()  
  45.     {  
  46.         if(this.product >= MAX_PRODUCT)  
  47.         {  
  48.             try  
  49.             {  
  50.                 wait();    
  51.                 System.out.println("产品已满,请稍候再生产");  
  52.             }  
  53.             catch(InterruptedException e)  
  54.             {  
  55.                 e.printStackTrace();  
  56.             }  
  57.             return;  
  58.         }  
  59.           
  60.         this.product++;  
  61.         System.out.println("生产者生产第" + this.product + "个产品.");  
  62.         notifyAll();   //通知等待区的消费者可以取出产品了  
  63.     }  
  64.       
  65.     /** 
  66.      * 消费者从店员取产品 
  67.      */  
  68.     public synchronized void getProduct()  
  69.     {  
  70.         if(this.product <= MIN_PRODUCT)  
  71.         {  
  72.             try   
  73.             {  
  74.                 wait();   
  75.                 System.out.println("缺货,稍候再取");  
  76.             }   
  77.             catch (InterruptedException e)   
  78.             {  
  79.                 e.printStackTrace();  
  80.             }  
  81.             return;  
  82.         }  
  83.           
  84.         System.out.println("消费者取走了第" + this.product + "个产品.");  
  85.         this.product--;  
  86.         notifyAll();   //通知等待去的生产者可以生产产品了  
  87.     }  
  88. }  
  89.   
  90.   
  91. /** 
  92.  * 生产品线程 
  93.  * @author admin 
  94.  * 
  95.  */  
  96. class Producer implements Runnable  
  97. {  
  98.     private Clerk clerk ;  
  99.       
  100.     public Producer(Clerk clerk)  
  101.     {  
  102.         this.clerk = clerk;  
  103.     }  
  104.       
  105.     public void run()   
  106.     {  
  107.         System.out.println("生产者开始生产产品.");  
  108.         while(true)  
  109.         {  
  110.             try   
  111.             {  
  112.                 Thread.sleep((int)(Math.random() * 10) * 100);  
  113.             }  
  114.             catch (InterruptedException e)   
  115.             {  
  116.                 e.printStackTrace();  
  117.             }  
  118.             clerk.addProduect(); //生产产品  
  119.         }  
  120.     }  
  121. }  
  122.   
  123. /** 
  124.  * 消费线程 
  125.  * @author admin 
  126.  * 
  127.  */  
  128. class Consumer implements Runnable  
  129. {  
  130.   
  131.     private Clerk clerk;  
  132.       
  133.     public Consumer(Clerk clerk)  
  134.     {  
  135.         this.clerk = clerk;  
  136.     }  
  137.       
  138.     public void run()   
  139.     {  
  140.         System.out.println("消费者开始取走产品.");  
  141.         while(true)  
  142.         {  
  143.             try   
  144.             {  
  145.                 Thread.sleep((int)(Math.random() * 10) * 100);  
  146.             }  
  147.             catch (InterruptedException e)   
  148.             {  
  149.                 e.printStackTrace();  
  150.             }  
  151.             clerk.getProduct();  //取产品  
  152.         }  
  153.     }  
  154.       
  155. }  




总结: 
      对wait,notify,notifyAll方法理解可以为归纳为图所示 

 

ps:最后一个o.notify是o.notifyAll,上传的时候没有注意到,抱歉了! 

posted @ 2016-12-08 17:19  天涯海角路  阅读(191)  评论(0)    收藏  举报