这个多线程java程序为什么会最开始执行同一个线程两次

packageexercise2;classComputer{privateintmfg=0;intstack=0;publicsynchronizedvoidmanuf... package exercise2;
class Computer {
private int mfg=0;
int stack=0;
public synchronized void manufacture(){
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

System.out.println("制造一台电脑");
mfg=1;
notify();
if(mfg==1){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}

}
}
public synchronized void transport(){
try {
Thread.sleep(50);
} catch (InterruptedException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

stack+=1;
mfg=0;
notify();
if(mfg==0){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
}
class producer implements Runnable{
Computer c=null;

public producer(Computer c) {
this.c = c;
}

@Override
public void run() {
while(true){
c.manufacture();
}
}

}
class Consumer implements Runnable{
Computer c=null;

public Consumer(Computer c) {
this.c = c;
}

@Override
public void run() {
while(true){
c.transport();
System.out.println("运走一台电脑");
}
}

}
public class Ex22_2 {

public static void main(String[] args) {
Computer c=new Computer();
Thread t1=new Thread(new producer(c));
Thread t2=new Thread(new Consumer(c));

t1.start();
t2.start();

try {
Thread.sleep(1500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t1.stop();
t2.stop();
System.out.println(c.stack);
}

}
运行结果
制造一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
14
展开
 我来答
紫薇参星
科技发烧友

2016-04-20 · 有一些普通的科技小锦囊
知道大有可为答主
回答量:5983
采纳率:92%
帮助的人:3492万
展开全部

Thread t1先执行调用c.manufacture();打印"制造一台电脑" t1等待被t2唤醒wait();

Thread t2执行时调用c.transport();但是没有打印"运走一台电脑"因为"运走一台电脑"没有在c.transport();中wait()前打印,而是在c.transport();调用后打印的,所以这里没有输出.
t2执行唤醒t1 notify();t2等待被t1唤醒wait();注意这时c.transport();并没有执行完,它还在等待被t1唤醒.

Thread t1再执行调用c.manufacture();打印"制造一台电脑" 唤醒t2 notify();这时c.transport();执行完了打印"运走一台电脑".然后t1等待被唤醒wait();

Thread t2执行时调用c.transport();但是没有打印"运走一台电脑"唤醒t1 notify();t2 wait();注意这时c.transport();并没有执行完,它还在等待被t1唤醒.

Thread t1执行调用c.manufacture();打印"制造一台电脑" 唤醒t2 notify();这时c.transport();执行完了打印"运走一台电脑".然后t1等待被唤醒wait();

上面是造成"制造一台电脑"在开头被打印两次的原因

解决办法就是把打印"运走一台电脑"放到c.transport();函数中wait();语句前,就不会出现打印两次的情况了.
像这样:完整的程序如下:

package exercise2;

class Computer { 

 private int mfg=1; 

 int stack=0; 

 public synchronized void manufacture(){  

  try {   

   Thread.sleep(50);  

  } catch (InterruptedException e1) {   

   // TODO Auto-generated catch block   

   e1.printStackTrace();  

  }    

  System.out.println("制造一台电脑");  

  mfg=1;  

  notify();  

  if(mfg==1){   

   try{    

    wait();   

   }catch(InterruptedException e){    

    e.printStackTrace();   

   }     

  } 

 } 

 public synchronized void transport(){  

  try {   

   Thread.sleep(50);  

  } catch (InterruptedException e1) {   

   // TODO Auto-generated catch block   

   e1.printStackTrace();  

  }   

  System.out.println("运走一台电脑");//这里加上打印语句  

  stack+=1;  

  mfg=0;  

  notify();  

  if(mfg==0){   

   try{    

    wait();   

   }catch(InterruptedException e){    

    e.printStackTrace();   

   }  

  } 

 }

}

class producer implements Runnable{ 

 Computer c=null; 

 public producer(Computer c) {  

  this.c = c; 

 } 

 @Override 

 public void run() {  

  while(true){   

   c.manufacture();  

  } 

 }

}

class Consumer implements Runnable{ 

 Computer c=null; 

 public Consumer(Computer c) {  

  this.c = c; 

 } 

 @Override 

 public void run() {  

  while(true){   

   c.transport();    

   //System.out.println("运走一台电脑");//这里去掉打印语句 移动到c.transport();函数中wait语句前

  } 

 } 

}

public class Ex22_2 { 

 public static void main(String[] args) {  

  Computer c=new Computer();  

  Thread t1=new Thread(new producer(c));  

  Thread t2=new Thread(new Consumer(c));    

  t1.start();  

  t2.start(); 

  

  try {   

   Thread.sleep(1500);  

  } catch (InterruptedException e) {   

   // TODO Auto-generated catch block   

   e.printStackTrace();  

  }  

  t1.stop();  

  t2.stop();  

  System.out.println(c.stack); 

 }

}

运行结果:

制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
运走一台电脑
制造一台电脑
14

piz168
推荐于2018-04-05 · 超过15用户采纳过TA的回答
知道答主
回答量:43
采纳率:100%
帮助的人:22.3万
展开全部
mfg=0这一句被t2抢到先于t1的mfg=1;执行,导致t1读到的mfg为0,进不了wait。
这个要用信号量来写啊,这么写肯定是有问题的。
本回答被网友采纳
已赞过 已踩过<
你对这个回答的评价是?
评论 收起
推荐律师服务: 若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询

为你推荐:

下载百度知道APP,抢鲜体验
使用百度知道APP,立即抢鲜体验。你的手机镜头里或许有别人想知道的答案。
扫描二维码下载
×

类别

我们会通过消息、邮箱等方式尽快将举报结果通知您。

说明

0/200

提交
取消

辅 助

模 式