class Producer implements Runnable
{
Q q=null;
public Producer(Q q)
{
this.q=q;
}
public void run()
{
int i=0;
while(true)
{
if(i==0)
q.put("张三","男");
else
q.put("李四","女");
i=(i+1)%2;
}
}
}
class Q
{
private String name="";
private String sex="";
boolean qfull=false;
public synchronized void put(String name,String sex)
{
if(qfull)
try{wait();}catch(Exception e){}
else
this.name=name;
try{Thread.currentThread().sleep(1); }catch(InterruptedException e){}
this.sex=sex;
qfull=true;
notify();
}
public synchronized void get()
{
if(!qfull)
try{wait();}catch(Exception e){}
System.out.println(name);
try{Thread.sleep(1); }catch(InterruptedException e){}
System.out.println(sex);
qfull=false;
notify();
}
}
class Consumer implements Runnable
{
Q q=null;
public Consumer(Q q)
{
this.q=q;
}
public void run()
{
while(true)
{
q.get();
}
}

public class A
{
public static void main(String [] args)
{
Q q=new Q();
new Thread(new Producer(q)).start();
new Thread(new Consumer(q)).start();
}
}
//try{Thread.currentThread().sleep(1); }catch(InterruptedExceptione){}程序不加这个代码会出现“张三,女”的输出,不是特别理解。按理put()和get()两个函数是同步的,消费者必须等到put()函数结束后才会调用get()函数的,不应该出现“张三,女”的紊乱输出。而且sleep()函数让生产者线程睡眠,怎么又保证了程序输出“张三,男”,“李四,女”的输出

解决方案 »

  1.   

    问题出现在你的if(qfull) 这里了,我替你修改成while就可以了
        while (qfull) {
          try {
            wait();
          } catch (Exception e) {}
        }和
        while (!qfull) {
          try {
            wait();
          } catch (Exception e) {}
        }原因自己分析吧。 
      

  2.   

    上面的时假象,这个才是关键
        if (qfull)
          try {
            wait();
          } catch (Exception e) {}
        else
          this.name = name;如果qfull, 你会等待,但是等待之后,不会运行那个this.name 那一句了改称
        if (qfull)
          try {
            wait();
          } catch (Exception e) {}
          this.name = name;就可以了!还真隐蔽
      

  3.   

    嗯,楼上正解
    当加上
    try{Thread.sleep(1);   }catch(InterruptedException   e){} 
    这句之后
    减小了两个线程冲突的几率可以在put方法的wait();后面写上 System.out.println("put wait");
    在get方法的wait();后面写上 System.out.println("get wait");看看在加 try{Thread.sleep(1);   }catch(InterruptedException   e){} 
    之前之后的变化