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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 冷延冰 中级黑马   /  2013-1-24 13:51  /  1200 人查看  /  3 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

毕老师在生产者消费者模式的版本一中,有两个线程来进行生产,两个对象负责消费。由于使用notify()方法唤醒了同一类的线程(同时负责消费或者生成的线程),所以造成了生产两次消费一次的情况。我在wait()之后加了else,原本在wait()后醒来继续向下执行,加过else后就要重新判断了,和老师的效果是一样的吧?
  1. class Res
  2. {
  3.         private String name;
  4.         private int count=1;
  5.         private boolean flag=false;
  6.        
  7.         public synchronized void set(String name)
  8.         {
  9.                 if(flag)
  10.                 {
  11.                         try
  12.                         {
  13.                                 this.wait();
  14.                         }
  15.                         catch(Exception e){}
  16.                 }
  17.                 else
  18.                 {
  19.                 this.name=name+"----"+count++;
  20.                 System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
  21.                 flag=true;
  22.                 notifyAll();       
  23.         }
  24.         }
  25.        
  26.         public synchronized void out()
  27.         {
  28.                 if(!flag)
  29.                 {
  30.                         try
  31.                         {
  32.                                 this.wait();
  33.                         }
  34.                         catch(Exception e){}
  35.                 }
  36.                 else
  37.                 {
  38.                 System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);
  39.                 flag=false;
  40.                 notifyAll();        }
  41.         }
  42. }
复制代码
不过由于本程序是在调用的时候使用了循环,如果调用没循环的话if else只执行一次,是不是多线程就没有意义了?
看到后面,新版本里面有了lock和condition好用多了

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

3 个回复

倒序浏览
{:soso__11759853488848172597_2:}
回复 使用道具 举报
单独看上面这一段代码的话是有问题的
如果线程在wait一次以后,被唤醒以后就不会执行else里面的 语句。因为if和else只能执行一个。
  1. class Res
  2. {
  3.         private String name;
  4.         private int count=1;
  5.         private boolean flag=false;
  6.         
  7.         public synchronized void set(String name)
  8.         {
  9.                 if(flag)
  10.                 {
  11.                         try
  12.                         {
  13.                                 this.wait();//如果线程在这里wait一次以后,被唤醒以后就不会执行else里面的 语句。因为if和else只能执行一个。
  14.                         }
  15.                         catch(Exception e){}
  16.                 }
  17.                 else
  18.                 {
  19.                 this.name=name+"----"+count++;
  20.                 System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
  21.                 flag=true;
  22.                 notifyAll();        
  23.         }
  24.         }
  25.         
  26.         public synchronized void out()
  27.         {
  28.                 if(!flag)
  29.                 {
  30.                         try
  31.                         {
  32.                                 this.wait();
  33.                         }
  34.                         catch(Exception e){}
  35.                 }
  36.                 else
  37.                 {
  38.                 System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);
  39.                 flag=false;
  40.                 notifyAll();        }
  41.         }
  42. }
复制代码
因为没有完整的代码,如果分析的不对,请见谅哈。。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1 神马都是浮云

查看全部评分

回复 使用道具 举报
本帖最后由 zyx67786110 于 2013-1-26 19:40 编辑

if的catch后边如果没有后边的操作数据的代码(即else里边的语句),你让程序线程停止是没有意义的,不如直接return结束该次调用,但就算是return你也浪费了一次执行机会,因为你获取了执行权,却没有处理数据。如果你把else里边的代码,在if的catch后边再copy一份的话,倒是每次都能处理数据,但那样就显得啰嗦了,不如将这段代码块直接放在if(){}后边。这样保证了处理不同数据处理操作的线程间的安全的,但没有保证相同数据处理操作的线程间的安全,所以在唤醒后,还需要每次在线程唤醒后都判断下flag,即加while控制。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1 神马都是浮云

查看全部评分

回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马