分享

关于Java多线程实现生产者和消费者的问题

 Java修炼馆 2011-09-27
在学习Java多线程并发编程的同时,自己写了一个用wait()和notifyAll()实现的生产者消费者相互阻塞,保持同步的程序。
设置产品缓冲区上限为8,可生产者检查counter计数器等于8的时候wait()并没有让多个生产者线程阻塞,而是继续向下执行,对此表示不解,还请诸位高手们给菜鸟弟弟我一个解答,感激不尽!


Java代码 复制代码 收藏代码
  1. /*  
  2. *   这是一个与多线程有关的以生产者消费者问题为原型的Java程序源码。  
  3. *   为了体验notify和notifyAll方法,我尝试开启十个生产者和五个消费者线程,对大小为8的缓冲区进行操作,要做到缓冲区产品达到8的时候,生产者线程阻塞,直到消费者线程减少缓冲区的产品数量,并对阻塞进程进行唤醒。  
  4. *   可现在的问题是,当生产者向缓冲区放入8个产品后,wait()方法并没有使生产者线程们停住,对此表示很疑惑。  
  5. *  
  6. */  
  7.   
  8.   
  9.   
  10. import java.util.concurrent.ExecutorService;   
  11. import java.util.concurrent.Executors;   
  12.   
  13. class myProducer implements Runnable   
  14. {   
  15.     private myProAndCon mpc;   
  16.        
  17.     myProducer( myProAndCon mpac ){ this.mpc =  mpac; }   
  18.        
  19.     public void run()   
  20.     {   
  21.         try {   
  22.             while(!Thread.interrupted())   
  23.             {      
  24.                     //生产者互斥   
  25.                     synchronized (this){   
  26.   
  27.                         //静态计数值达到上限,则wait()阻塞,等待被消费者线程唤醒   
  28.                         while ( mpc.get() >= 8 )   
  29.                            
  30.                         {   
  31.                        
  32.                             System.out.println(mpc.get());   
  33.                                 wait();   
  34.                         }   
  35.                     }   
  36.                        
  37.                     Thread.sleep(100);   
  38.                        
  39.                     //未发生阻塞时,向缓冲区内放入产品,增加计数值,并唤醒所有阻塞的消费者线程   
  40.                     synchronized ( mpc.c ){   
  41.                             System.out.println("[ P ] The number is " + mpc.inc() );   
  42.                             mpc.c.notifyAll();   
  43.                     }   
  44.             }   
  45.         } catch (InterruptedException e) {   
  46.             // TODO Auto-generated catch block   
  47.             e.printStackTrace();   
  48.         }   
  49.     }   
  50. }   
  51.   
  52.   
  53. class myConsumer implements Runnable   
  54. {   
  55.     private myProAndCon mpc;   
  56.        
  57.     myConsumer( myProAndCon mpac ){ this.mpc =  mpac; }   
  58.        
  59.     public void run()   
  60.     {      
  61.         try {   
  62.             while(!Thread.interrupted())   
  63.             {   
  64.                 //消费者互斥   
  65.                 synchronized ( this )   
  66.                 {   
  67.                     //当缓冲区无产品时,消费者线程阻塞,等待被生产者线程唤醒   
  68.                     while ( mpc.get() <= 0 )   
  69.                         wait();   
  70.                 }   
  71.                    
  72.                 Thread.sleep(3000);   
  73.                    
  74.                 //未发生阻塞时,从缓冲区取出产品,减少计数值,并唤醒所有阻塞的生产者线程   
  75.                 synchronized (mpc.p){   
  76.                         System.out.println("[ C ] The number is " + mpc.dec() );   
  77.                         mpc.p.notifyAll();   
  78.                 }   
  79.                        
  80.                    
  81.             }   
  82.         } catch (InterruptedException e) {   
  83.             // TODO Auto-generated catch block   
  84.             e.printStackTrace();   
  85.         }   
  86.            
  87.     }   
  88. }   
  89.   
  90.   
  91.   
  92.   
  93. public class myProAndCon {   
  94.     //public final int S = 8;   
  95.   
  96.     //缓冲区计数器(静态)以及对其进行的三个synchronized操作   
  97.     volatile private static int  counter = 0;   
  98.        
  99.     synchronized static int inc(){ return ++ counter; }   
  100.     synchronized static int dec(){ return  counter -= 2; }   
  101.     synchronized static int get(){ return  counter; }   
  102.   
  103.     //构造两个对象,作为开启线程的参数   
  104.     public myConsumer c = new myConsumer(this);   
  105.     public myProducer p = new myProducer(this);   
  106.        
  107.     private ExecutorService exec = Executors.newCachedThreadPool();   
  108.        
  109.     public myProAndCon(){   
  110.            
  111.         //打开十个生产者线程   
  112.         for ( int i  = 0 ; i < 10 ; i ++ )   
  113.             exec.execute(p);   
  114.            
  115.         //打开五个消费者线程   
  116.         for  ( int i = 0 ; i < 5 ; i ++ )   
  117.             exec.execute(c);   
  118.            
  119.     }   
  120.        
  121.   
  122.     //主函数调用myProAndCon类构造方法,开始执行各个线程   
  123.     public static void main(String[] s)   
  124.     {   
  125.         new myProAndCon();   
  126.     }   
  127.        
  128.        

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多