以下这段代码来自某教程
对执行结果困惑,请求高手解释一下class Test extends Thread
{
public static void main(String[] args) //throws Exception
{
Queue q=new Queue();
Producer p=new Producer(q);
Consumer c=new Consumer(q);
p.start();
c.start();
}
}
class Producer extends Thread
{
Queue q;
Producer(Queue q)
{
this.q=q;
}
public void run()
{
for(int i=0;i<10;i++)
{
q.put(i);
System.out.println("producer put "+i);
}
}
}
class Consumer extends Thread
{
Queue q;
Consumer(Queue q)
{
this.q=q;
}
public void run()
{
for(int j=0;j<10;j++)
System.out.println("consumer get "+q.get());
}
}
class Queue
{
int i;
boolean b=false;
public synchronized void put(int i)
{
if(!b)
{
//System.out.println("producer put "+i);
this.i=i;
b=true;
notify();
}
try
{
wait();
}
catch(Exception e){}
}
public synchronized int get()
{
if(!b)
{
try
{
wait();
}
catch(Exception e){}
}
b=false;
notify();
return i;
}
}
我试了将Producer和Consumer类run()中的循环次数从3次一直改到10次
得到好几种打印顺序,想弄明白结果不一样的原因是什么
对执行结果困惑,请求高手解释一下class Test extends Thread
{
public static void main(String[] args) //throws Exception
{
Queue q=new Queue();
Producer p=new Producer(q);
Consumer c=new Consumer(q);
p.start();
c.start();
}
}
class Producer extends Thread
{
Queue q;
Producer(Queue q)
{
this.q=q;
}
public void run()
{
for(int i=0;i<10;i++)
{
q.put(i);
System.out.println("producer put "+i);
}
}
}
class Consumer extends Thread
{
Queue q;
Consumer(Queue q)
{
this.q=q;
}
public void run()
{
for(int j=0;j<10;j++)
System.out.println("consumer get "+q.get());
}
}
class Queue
{
int i;
boolean b=false;
public synchronized void put(int i)
{
if(!b)
{
//System.out.println("producer put "+i);
this.i=i;
b=true;
notify();
}
try
{
wait();
}
catch(Exception e){}
}
public synchronized int get()
{
if(!b)
{
try
{
wait();
}
catch(Exception e){}
}
b=false;
notify();
return i;
}
}
我试了将Producer和Consumer类run()中的循环次数从3次一直改到10次
得到好几种打印顺序,想弄明白结果不一样的原因是什么
producer put 0
consumer get 0
producer put 1
consumer get 1
producer put 2
consumer get 2
producer put 3
consumer get 3
consumer get 4
producer put 4
consumer get 5
producer put 5
consumer get 6
producer put 6
consumer get 7
producer put 7
consumer get 8
producer put 8
producer put 9
consumer get 9不明白的地方是,
第1行为什么不是打印get 0(p线程执行第一次循环时,当它被wait时,打印语句应该还未执行,这时c线程启动)
get3和get4接连打印出来,从get4开始变成get-put对
一直到put8和put9,又变回put-get对
把c线程中("consumer get "+q.get());
改为cc=q.get();Thread.sleep(10000);("consumer get "+cc);
就不难发现该问题:执行q.get()时,系统可能发生还未来得及执行消费者线程的打印语句(("consumer get "+q.get());)呢,生产者线程就收到notify指令被放开,去执行System.out.println("producer put "+i);自然会出现先put 0再get 0的现象。对于顺序不一致的问题,这也是肯定的,你的wait()和notify()及互斥信号量b针对的仅仅是c线程和p线程中的queue线程而非c和p线程本生,c,p线程中的打印语句自然不受wait()和notify()及互斥信号量b的控制,所以尽管c,p线程中的queue线程得到了控制,但c,p线程中的打印语句是并发的,出现的顺序自然也就是随机的。
若要做到对c,p线程的控制,wait()和notify()需要在c,p线程内部设置,而不是其它的第3个线程。class Test extends Thread
{
public static void main(String[] args) //throws Exception
{
Queue q=new Queue();
Producer p=new Producer(q);
Consumer c=new Consumer(q);
p.start();
c.start();
}
}
class Producer extends Thread
{
Queue q;
Producer(Queue q)
{
this.q=q;
}
public void run()
{
for(int i=0;i<1;i++)
{
q.put(i);
System.out.println("producer put "+i);
}
}
}
class Consumer extends Thread
{
Queue q;
int cc;
Consumer(Queue q)
{
this.q=q;
}
public void run()
{
for(int j=0;j<1;j++)
try
{
cc=q.get();
Thread.sleep(1000);
}
catch(Exception e ){}
System.out.println("consumer get "+cc);
}
}
class Queue
{
int i;
boolean b=false;
public synchronized void put(int i)
{
if(!b)
{
//System.out.println("producer put "+i);
this.i=i;
b=true;
notify();
}
try
{
wait();
}
catch(Exception e){}
}
public synchronized int get()
{
if(!b)
{
try
{
wait();
}
catch(Exception e){}
}
b=false;
notify();
return i;
}
}