日期:2014-05-20  浏览次数:20745 次

线程异步、同步问题。。请各位大侠帮忙呀!!!
class Info{ // 定义信息类
private String name = "李兴华"; // 定义name属性
private String content = "JAVA讲师" ; // 定义content属性
private boolean flag = false ; // 设置标志位
public synchronized void set(String name,String content){
if(!flag){
try{
super.wait() ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
}
this.setName(name) ; // 设置名称
try{
Thread.sleep(300) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
this.setContent(content) ; // 设置内容
flag = false ; // 改变标志位,表示可以取走
super.notify() ;
}
public synchronized void get(){
if(flag){
try{
super.wait() ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
}
try{
Thread.sleep(300) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
System.out.println(this.getName() + 
" --> " + this.getContent()) ;
flag = true ; // 改变标志位,表示可以生产
super.notify() ;
}
public void setName(String name){
this.name = name ;
}
public void setContent(String content){
this.content = content ;
}
public String getName(){
return this.name ;
}
public String getContent(){
return this.content ;
}
};
class Producer implements Runnable{ // 通过Runnable实现多线程
private Info info = null ; // 保存Info引用
public Producer(Info info){
this.info = info ;
}
public void run(){
boolean flag = false ; // 定义标记位
for(int i=0;i<50;i++){
if(flag){
this.info.set("李兴华","JAVA讲师") ; // 设置名称
flag = false ;
}else{
this.info.set("mldn","www.mldnjava.cn") ; // 设置名称
flag = true ;
}
}
}
};
class Consumer implements Runnable{
private Info info = null ;
public Consumer(Info info){
this.info = info ;
}
public void run(){
for(int i=0;i<50;i++){
this.info.get() ;
}
}
};
public class ThreadCaseDemo03{
public static void main(String args[]){
Info info = new Info(); // 实例化Info对象
Producer pro = new Producer(info) ; // 生产者
Consumer con = new Consumer(info) ; // 消费者
new Thread(pro).start() ;
new Thread(con).start() ;
}
};

为什么我的程序还是会执行五十次呢???如果生产者抢到CPU,但此时存在商品。然后就会导致生产者的线程休眠。无法制造商品了。然后这次机会就错了。。但是i++会记一次数值呀。。但为什么我运行下来。。结果还是消费了五十次商品。????消费了五十次也就意味着创造了五十次。。我这样理解对吧。但是这样明显不符合理论呀。。求助!!!

------解决方案--------------------
怎么不符合了,你循环了50次,当然就打印50次了
你的flag会让生产者休眠,但是没有让生产者停止设置信息,即时停止设置信息,也只是让此次的信息丢失(也就是会保存上次的信息,消费者继续消费的时候取的是上次的信息不是新的信息),消费次数并不会改变

LZ注意体会一下以下代码的细微区别,你想要的结果可能是以下的处理(发生打印丢失)
Java code
public synchronized void get(){
if(flag){
try{
super.wait() ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
} else { //LZ在这里用else的话,结果就不一样了,也就是说发生打印丢失了
try{
Thread.sleep(300) ;
}catch(InterruptedException e){
e.printStackTrace() ;
}
System.out.println(this.getName() +  
" --> " + this.getContent()) ;
} //else的花括号
flag = true ; // 改变标志位,表示可以生产
super.notify() ;
}

------解决方案--------------------
探讨
为什么我的程序还是会执行五十次呢???如果生产者抢到CPU,但此时存在商品。然后就会导致生产者的线程休眠。无法制造商品了。然后这次机会就错了。。但是i++会记一次数值呀。。但为什么我运行下来。。结果还是消费了五十次商品。????消费了五十次也就意味着创造了五十次。。我这样理解对吧。但是这样明显不符合理论呀