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

2024年11月18日 10:30
有2个网友回答
网友(1):

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

网友(2):

mfg=0这一句被t2抢到先于t1的mfg=1;执行,导致t1读到的mfg为0,进不了wait。
这个要用信号量来写啊,这么写肯定是有问题的。