这个多线程java程序为什么会最开始执行同一个线程两次
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 展开
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