A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 邓士林 于 2015-1-26 17:23 编辑

题目连接黑马程序员技术分活动第31期,昨天看到这题,自己也琢磨了。
根据毕老师的讲解,我们是将生产和消费定义在了资源产品类中,这样可以简化很多判断和变量的定义。
具体代码体现:
  1. /*
  2. 等待的目的是让cpu给其他线程。
  3. */  
  4. class Resource  
  5. {  
  6.     private String name;  
  7.     private int count = 0;  
  8.     private boolean flag = false;  
  9.     Resource(String name)  
  10.     {  
  11.         this.name = name;  
  12.     }  
  13.   
  14.     public synchronized void product()  
  15.     {  
  16.         while(flag)                     //此处如果是if的效果  
  17.         {  
  18.             try  
  19.             {  
  20.                 wait();  
  21.             }  
  22.             catch (InterruptedException ex)  
  23.             {  
  24.                   
  25.             }  
  26.         }  
  27.   
  28.         this.name = "---"+this.count;  
  29.         System.out.println(Thread.currentThread().getName() + "生产者---" + this.name);  
  30.         flag  = true;  
  31.         this.count++;  
  32.         this.notify();  
  33.     }  
  34.       
  35.     public synchronized void consume()  
  36.     {  
  37.         while(!flag)                    //此处如果是if的效果,如果某个线程被wait,接着又一个,然后两个都醒了,就会造成对一个产品两次消费  
  38.         {  
  39.             try  
  40.             {  
  41.                 wait();  
  42.             }  
  43.             catch (InterruptedException ex)  
  44.             {  
  45.             }  
  46.         }  
  47.   
  48.         System.out.println(Thread.currentThread().getName() + "消费者---------" + this.name);  
  49.         flag = false;  
  50.         this.notify();  
  51.     }  
  52. }  
  53.   
  54. class Product implements Runnable  
  55. {  
  56.     private Resource sr;  
  57.     Product(Resource sr)  
  58.     {  
  59.         this.sr = sr;  
  60.     }  
  61.   
  62.     public void run()  
  63.     {  
  64.         while(true)  
  65.         {  
  66.             if(sr != null)  
  67.             {  
  68.                 sr.product();  
  69.             }  
  70.         }  
  71.     }  
  72. }  
  73.   
  74. class Consume implements Runnable  
  75. {  
  76.     private Resource sr;  
  77.     Consume(Resource sr)  
  78.     {  
  79.         this.sr = sr;  
  80.     }  
  81.   
  82.     public void run()  
  83.     {  
  84.         while(true)  
  85.         {  
  86.             if(sr != null)  
  87.             {  
  88.                 sr.consume();  
  89.             }  
  90.         }  
  91.     }  
  92. }  
  93. class DemoRunnable  
  94. {  
  95.     public static void main(String[] args)   
  96.     {  
  97.         Resource sr = new Resource("产品");  
  98.         Product p = new Product(sr);  
  99.         Consume c =new Consume(sr);  
  100.         Thread t1 = new Thread(p);  
  101.         Thread t2 = new Thread(p);  
  102.         Thread c1 = new Thread(c);  
  103.         Thread c2 = new Thread(c);  
  104.         Thread c3 = new Thread(c);  
  105.         t1.start();  
  106.         t2.start();  
  107.         c1.start();  
  108.         c2.start();  
  109.         c3.start();  
  110.     }  
  111. }
复制代码

4 个回复

倒序浏览
本帖最后由 邓士林 于 2015-1-9 11:22 编辑

下面请教大家的问题是,如果我把生产和消费定义在线程中去控制,而不是在资源产品类中进行控制,出现问题:
代码如下:
  1. class Resource
  2. {
  3.         private int id;
  4.         public boolean flag = false;//没产品
  5.         public String name;
  6.         Resource(int id)
  7.         {
  8.                 this.id = id;
  9.         }

  10.         public void setId(int id)
  11.         {
  12.                 this.id = id;
  13.         }
  14.         public int getId()
  15.         {
  16.                 return this.id;
  17.         }
  18. }
  19. class Product implements Runnable
  20. {
  21.         private Resource rs = null;
  22.         private int id = 0;
  23.         Product(Resource rs)
  24.         {
  25.                 this.rs = rs;
  26.         }

  27.         public void run()
  28.         {
  29.                 synchronized(this)                                //this.getClass()
  30.                 {
  31.                         while(true)
  32.                         {
  33.                                 if(rs.flag)
  34.                                 {
  35.                                         try
  36.                                         {
  37.                                                 this.wait();
  38.                                         }
  39.                                         catch (InterruptedException ex)
  40.                                         {
  41.                                         }
  42.                                 }

  43.                                 rs.name = ""+rs.getId();
  44.                                 System.out.println(Thread.currentThread().getName() + "生产一个产品,产品号:" +
  45.                                 rs.name);
  46.                                 rs.setId(++id);
  47.                                 rs.flag = true;        
  48.                                 this.notify();//有产品了
  49.                         }
  50.                 }
  51.         }
  52. }

  53. class Consum implements Runnable
  54. {
  55.         private Resource rs = null;
  56.         Consum(Resource rs)
  57.         {
  58.                 this.rs = rs;
  59.         }

  60.         public void run()
  61.         {
  62.                 synchronized(this)            //this.getClass()
  63.                 {
  64.                         while(true)
  65.                         {
  66.                                 if(!rs.flag)                                //没产品,等待,不进行消费
  67.                                 {
  68.                                         try
  69.                                         {
  70.                                                 this.wait();
  71.                                         }
  72.                                         catch (InterruptedException ex)
  73.                                         {
  74.                                         }
  75.                                 }
  76.                                 System.out.println(Thread.currentThread().getName() + "取出一个产品,产品号:" +
  77.                                 rs.name);
  78.                                 rs.flag = false;
  79.                                 this.notify();
  80.                         }
  81.                 }
  82.         }
  83. }

  84. class ThreadTest
  85. {
  86.         public static void main(String [] args)
  87.         {
  88.                 Resource rs =new Resource(0);
  89.                 Product p = new Product(rs);
  90.                 Consum c = new Consum(rs);
  91.                 Thread tp1 = new Thread(p);
  92.                 Thread tp2 = new Thread(p);
  93.                 Thread tc1 =new Thread(c);
  94.                 Thread tc2 =new Thread(c);
  95.                 Thread tc3 =new Thread(c);

  96.                 tp1.start();
  97.                 tp2.start();
  98.                 tc1.start();
  99.                 tc2.start();
  100.                 tc3.start();

  101.         }
  102. }
复制代码

ddd.png (11.03 KB, 下载次数: 33)

ddd.png
回复 使用道具 举报
本帖最后由 godmmm 于 2015-1-9 12:04 编辑

应该是锁加错了,this表示的本类,这样你的生存者用的是一个类锁,消费者用的是另一个锁,这样切换不了,你用资源这个锁试试。
回复 使用道具 举报
godmmm 发表于 2015-1-9 11:55
应该是锁加错了,this表示的本类,这样你的生存者用的是一个类锁,消费者用的是另一个锁,这样切换不了,你 ...

我知道,可是没想明白如何做呢
回复 使用道具 举报
你等待和唤醒的是this对象,这就错了,应该是锁这个对象
等待唤醒机制wait和notify只能是同一个对象
  1. class Resource {
  2.         private int id;
  3.         public boolean flag = false;// 没产品
  4.         public String name;

  5.         Resource(int id) {
  6.                 this.id = id;
  7.         }

  8.         public void setId(int id) {
  9.                 this.id = id;
  10.         }

  11.         public int getId() {
  12.                 return this.id;
  13.         }
  14. }
  15. class Product implements Runnable {
  16.         private Resource rs = null;
  17.         private int id = 0;

  18.         Product(Resource rs) {
  19.                 this.rs = rs;
  20.         }

  21.         public void run() {
  22.                 for(;;)
  23.                 {
  24.                         set();
  25.                 }
  26.         }
  27.         public  void set()
  28.         {
  29.                 synchronized(rs.getClass())
  30.                 {
  31.                         while (true) {
  32.                                 if (rs.flag)
  33.                                 {
  34.                                         try {rs.getClass().wait();} catch (InterruptedException ex) {}
  35.                                 }
  36.                                
  37.                                 rs.name = "" + rs.getId();
  38.                                 System.out.println(Thread.currentThread().getName()+ "生产一个产品,产品号:" + rs.name);
  39.                                 rs.setId(++id);
  40.                                 rs.flag = true;
  41.                                 rs.getClass().notify();// 有产品了
  42.                         }
  43.                 }
  44.         }
  45. }

  46. class Consum implements Runnable {
  47.         private Resource rs = null;

  48.         Consum(Resource rs) {
  49.                 this.rs = rs;
  50.         }

  51.         public void run() {
  52.                 for(;;)
  53.                 {
  54.                         get();
  55.                 }
  56.         }
  57.         public  void get()
  58.         {
  59.                 synchronized(rs.getClass())
  60.                 {
  61.                         while (true) {
  62.                                 if (!rs.flag) // 没产品,等待,不进行消费
  63.                                 {
  64.                                         try {rs.getClass().wait();} catch (InterruptedException ex) {}
  65.                                 }
  66.                                 System.out.println(Thread.currentThread().getName()        + "取出一个产品,产品号:" + rs.name);
  67.                                 rs.flag = false;
  68.                                 rs.getClass().notify();
  69.                         }
  70.                 }
  71.         }
  72. }

  73. class ThreadTest {
  74.         public static void main(String[] args) {
  75.                 Resource rs = new Resource(0);
  76.                 Product p = new Product(rs);
  77.                 Consum c = new Consum(rs);
  78.                 Thread tp1 = new Thread(p);
  79.                 Thread tp2 = new Thread(p);
  80.                 Thread tc1 = new Thread(c);
  81.                 Thread tc2 = new Thread(c);
  82.                 Thread tc3 = new Thread(c);

  83.                 tp1.start();
  84.                 tp2.start();
  85.                 tc1.start();
  86.                 tc2.start();
  87.                 tc3.start();

  88.         }
  89. }
复制代码
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马