生产者消费者之爸爸妈妈儿子女儿苹果橘子编程实现

桌上有一个空盘子,只允许放一个水果。爸爸可以向盘中放苹果,也可以向盘中放桔子,儿子专等吃盘中的桔子,女儿专等吃盘中的苹果。规定当盘空时,一次只能放一只水果。

下面是程序的具体实现代码,在写这个程序的时候,有点小问题,纠结了很长时间,于是在csdn论坛上发表帖子终于得到了解决

先说说涉及到的类的作用,首先Fruits作为一个水果的父类,Apple和Orange是Fruits类的扩展类。CriticalResources类是临界资源类,作为缓冲区用,里面封装了数组大小为一的Fruits数组,可以看成“盘子”;ProducerOrange为生产橘子的类 ProducerApple为生产桔子的类 ConsumerApple(消费苹果的类) ConsumerOrange(消费桔子的类)

水果类代码如下

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. public class Fruits {  
  4.     private String name;  
  5.   
  6.     public Fruits(String name) {  
  7.         this.name = name;  
  8.     }  
  9.   
  10.     @Override  
  11.     public String toString() {  
  12.         return name;  
  13.     }  
  14.   
  15.     public Fruits() {  
  16.         super();  
  17.     }  
  18.   
  19. }  

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. /** 
  4.  * @author zhuyong  
  5.  * 创建时间:2012-6-6 上午09:46:14 
  6.  * 类说明 : 
  7.  */  
  8. public class Orange extends Fruits {  
  9.   
  10.     public Orange() {  
  11.         super();  
  12.         // TODO Auto-generated constructor stub  
  13.     }  
  14.   
  15.     public Orange(String name) {  
  16.         super(name);  
  17.         // TODO Auto-generated constructor stub  
  18.     }  
  19.       
  20. }  
[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. /** 
  4.  * @author zhuyong  
  5.  * 创建时间:2012-6-6 上午09:46:14 
  6.  */  
  7. public class Apple extends Fruits {  
  8.   
  9.     public Apple() {  
  10.         super();  
  11.         // TODO Auto-generated constructor stub  
  12.     }  
  13.   
  14.     public Apple(String name) {  
  15.         super(name);  
  16.         // TODO Auto-generated constructor stub  
  17.     }  
  18.       
  19. }  


下面是作为缓冲区盘子的代码

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. public class CriticalResources {  
  4.     private int index = 0;  
  5.     private static Fruits[] fruites = new Fruits[1];// 默认临界区有五个商品  
  6.     private ProducerApple pa = new ProducerApple(this);  
  7.     private ProducerOrange po = new ProducerOrange(this);  
  8.     private ConsumerApple ca = new ConsumerApple(this);  
  9.     private ConsumerOrange co = new ConsumerOrange(this);  
  10.   
  11.     /** 
  12.      * 向临界资源里添加商品 利用synchronized关键字实现同步 添加后数组指针+1 
  13.      * 如果临界资源数组里面装满了商品不能再生产,则生产线程等待以便让消费者消费 
  14.      *  
  15.      * @param goods 
  16.      */  
  17.     public synchronized void push(Fruits goods) {  
  18.         //  
  19.         while (this.index == this.fruites.length) {  
  20.             try {  
  21.                 this.wait();  
  22.             } catch (InterruptedException e) {  
  23.                 // TODO Auto-generated catch block  
  24.                 e.printStackTrace();  
  25.             }  
  26.         }  
  27.   
  28.         this.notifyAll();// 唤醒生产者  
  29.         this.fruites[index++] = goods;  
  30.   
  31.     }  
  32.   
  33.     /** 
  34.      * 从临界资源里拿商品,先减一后返回 如果index==0说明, 临界资源数组里面没有商品,不能在消费 消费线程阻塞, 让生产者生产 则让生产者 
  35.      *  
  36.      * @return 
  37.      */  
  38.     public synchronized Fruits pop() {  
  39.         while (this.index == 0) {  
  40.             try {  
  41.                 this.wait();  
  42.             } catch (InterruptedException e) {  
  43.                 // TODO Auto-generated catch block  
  44.                 e.printStackTrace();  
  45.             }  
  46.         }  
  47.   
  48.         this.notifyAll();// 唤醒消费者  
  49.         return fruites[--index];  
  50.   
  51.     }  
  52.   
  53.     /** 
  54.      * 看看是不是空了 
  55.      *  
  56.      * @return 
  57.      */  
  58.     public synchronized Fruits peek() {  
  59.         if (this.index == 0)  
  60.             return null;  
  61.         else  
  62.             return fruites[index - 1];  
  63.     }  
  64.   
  65.     public int getIndex() {  
  66.         return index;  
  67.     }  
  68.   
  69.     public void setIndex(int index) {  
  70.         this.index = index;  
  71.     }  
  72.   
  73.     public Fruits[] getFruites() {  
  74.         return fruites;  
  75.     }  
  76.   
  77. }  


下面是生产桔子和消费桔子的代码

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. public class ProducerOrange implements Runnable {  
  4.     CriticalResources cr = null;  
  5.   
  6.     public ProducerOrange(CriticalResources cr) {  
  7.         super();  
  8.         this.cr = cr;  
  9.     }  
  10.     int count = 5; //做5次  
  11.   
  12.     @Override  
  13.     public void run() {  
  14.          while(count-->0)  
  15.                 synchronized (cr) {  
  16.                     while (cr.peek() != null) {  
  17.                         try {  
  18.                             cr.wait();// 该生产这等待  
  19.                         } catch (InterruptedException e) {  
  20.                             // TODO Auto-generated catch block  
  21.                             e.printStackTrace();  
  22.                         }  
  23.                     }  
  24.                     Fruits fruits = new Orange("橘子");  
  25.                     cr.push(fruits);  
  26.                     System.out.println("橘子生产商生产了" + fruits);  
  27.                     cr.notifyAll();  
  28.                 }  
  29.   
  30.     }  
  31.   
  32. }  


 

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. /** 
  4.  * 消费橘子的消费者 
  5.  *  
  6.  * @author Administrator 
  7.  *  
  8.  */  
  9. public class ConsumerOrange implements Runnable {  
  10.   
  11.     private CriticalResources cr = null;// 封装一个临界资源对象,以便消费  
  12.   
  13.     public ConsumerOrange(CriticalResources cr) {  
  14.         super();  
  15.         this.cr = cr;  
  16.     }  
  17.   
  18.     int count = 5;  
  19.   
  20.     @Override  
  21.     public void run() {  
  22.   
  23.         while (count-- > 0)  
  24.             // 如果缓冲区是苹果  
  25.             synchronized (cr) {  
  26.                 while (!(cr.peek() instanceof Orange)) {  
  27.                     try {  
  28.                         cr.wait();// 该消费者等待  
  29.                     } catch (InterruptedException e) {  
  30.                         // TODO Auto-generated catch block  
  31.                         e.printStackTrace();  
  32.                     }  
  33.                 }  
  34.                 Fruits fruits = cr.pop();  
  35.   
  36.                 System.out.println("----橘子消费者消费了-------" + fruits);  
  37.                 cr.notifyAll();  
  38.             }  
  39.   
  40.     }  
  41.   
  42. }  


下面是生产苹果核消费苹果的代码

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3.   
  4. /** 
  5.  * 生产苹果的生产者 
  6.  *  
  7.  * @author Arthur 
  8.  *  
  9.  */  
  10. public class ProducerApple implements Runnable {  
  11.     private CriticalResources cr = null;// 封装一个临界资源对象,以便生产  
  12.   
  13.     public ProducerApple(CriticalResources cr) {  
  14.         super();  
  15.         this.cr = cr;  
  16.     }  
  17.   
  18.     private int count = 5;  
  19.   
  20.     @Override  
  21.     public void run() {  
  22.         while (count-- > 0)  
  23.             synchronized (cr) {  
  24.                 while ((cr.peek() != null)) {  
  25.                     try {  
  26.                         cr.wait();// 缓冲区满,该生产者等待  
  27.                     } catch (InterruptedException e) {  
  28.                         e.printStackTrace();  
  29.                     }  
  30.                 }  
  31.                 //如果不加锁,此处容易被打断  
  32.                 Fruits fruits = new Apple("苹果");  
  33.                 cr.push(fruits);  
  34.                 System.out.println("苹果生产商生产了" + fruits);  
  35.                 cr.notifyAll();  
  36.             }  
  37.   
  38.     }  
  39.   
  40. }  


 

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. /** 
  4.  * 消费苹果的消费者 
  5.  *  
  6.  * @author Arthur 
  7.  *  
  8.  */  
  9. public class ConsumerApple implements Runnable {  
  10.     private CriticalResources cr = null;// 封装一个临界资源对象,以便消费  
  11.   
  12.     public ConsumerApple(CriticalResources cr) {  
  13.         super();  
  14.         this.cr = cr;  
  15.     }  
  16. int count = 5;  
  17.     @Override  
  18.     public void run() {  
  19.          while(count-->0)  
  20.                 synchronized (cr) {  
  21.                     while (!(cr.peek() instanceof Apple) ) {  
  22.                         try {  
  23.                             cr.wait();  
  24.                         } catch (InterruptedException e) {  
  25.                             e.printStackTrace();  
  26.                         }  
  27.                     }  
  28.                     Fruits fruits = cr.pop();  
  29.   
  30.                     System.out.println("----苹果消费者消费了-------" + fruits);  
  31.                     cr.notifyAll();  
  32.                       
  33.                 }  
  34.   
  35.   
  36.     }  
  37. }  


客户端代码

[java] view plain copy
 
  1. package com.bankht.producerCustomer;  
  2.   
  3. public class Client {  
  4.   
  5.       /** 
  6.      * @param args 
  7.      */  
  8.     public static void main(String[] args) {  
  9.         CriticalResources cr = new CriticalResources();  
  10.         // 生产苹果实例  
  11.         ProducerApple appleP = new ProducerApple(cr);  
  12.         // 消费苹果实例  
  13.         ConsumerApple appleC = new ConsumerApple(cr);  
  14.   
  15.         // 橘子生产者实例  
  16.         ProducerOrange orangeP = new ProducerOrange(cr);  
  17.         // 橘子消费者实例  
  18.         ConsumerOrange orangeC = new ConsumerOrange(cr);  
  19.         // 生产苹果线程  
  20.         Thread pThread = new Thread(appleP);  
  21.         // 消费苹果线程  
  22.         Thread cThread = new Thread(appleC);  
  23.         // 生产橘子线程  
  24.         Thread pt = new Thread(orangeP);  
  25.         // 消费橘子线程  
  26.         Thread ct = new Thread(orangeC);  
  27.   
  28.          
  29.   
  30.         pThread.start();  
  31.         cThread.start();  
  32.         pt.start();  
  33.         ct.start();  
  34.     }  
  35.   
  36. }  


运行结果:

 

[html] view plain copy
 
  1. 苹果生产商生产了苹果  
  2. ----苹果消费者消费了-------苹果  
  3. 橘子生产商生产了橘子  
  4. ----橘子消费者消费了-------橘子  
  5. 苹果生产商生产了苹果  
  6. ----苹果消费者消费了-------苹果  
  7. 橘子生产商生产了橘子  
  8. ----橘子消费者消费了-------橘子  
  9. 苹果生产商生产了苹果  
  10. ----苹果消费者消费了-------苹果  
  11. 橘子生产商生产了橘子  
  12. ----橘子消费者消费了-------橘子  
  13. 苹果生产商生产了苹果  
  14. ----苹果消费者消费了-------苹果  
  15. 橘子生产商生产了橘子  
  16. ----橘子消费者消费了-------橘子  
  17. 苹果生产商生产了苹果  
  18. ----苹果消费者消费了-------苹果  
  19. 橘子生产商生产了橘子  
  20. ----橘子消费者消费了-------橘子