一段关于线程的代码 请教

代码如下:
目的是要打出“张三”“男”,“李四”“女”。但是我只能打印出“张三”的信息,却无法打印出“李四”的信息,请问这是怎么回事?谢谢

class Producer implements Runnable
{
Q q;
public Producer(Q q)
{
this.q = q;
}
public void run()
{
int i=0;
while(true)
{
synchronized(q)
{
if(i==0)
{
q.name="zhangsan";
try{Thread.sleep(1);}catch(Exception e){}
q.sex="male";
System.out.println(i);
}
else
{
q.name="lisi";
q.sex="female";
}

}
i=(i+1)%2;
}

}

}

class Consumer implements Runnable
{
Q q;
public Consumer(Q q)
{
this.q = q;
}
public void run()
{
while(true)
{
synchronized(q)
{
System.out.print(q.name);
System.out.println(":" + q.sex);
}
}
}
}

class Q
{
String name="unknown";
String sex="unknown";
}

class ThreadCommunication
{
public static void main(String[] args)
{
Q q = new Q();
new Thread(new Producer(q)).start();
new Thread(new Consumer(q)).start();
}
}

对不起,你真的应该用[code]来框下,我没有看到你的[b]}[/b]

synchronized(q),2个线程很公平的获得q这个对象的monitor,也就是获得锁
[code="java"]
while(true)
{
synchronized(q)
{
System.out.print(q.name);
System.out.println(":" + q.sex);
}
}
[/code]

另外一个是
[code="java"]
while(true)
{
synchronized(q)
{
if(i==0)
{
q.name="zhangsan";
try{Thread.sleep(1);}catch(Exception e){}
q.sex="male";
System.out.println(i);
}
else
{
q.name="lisi";
q.sex="female";
}

}
i=(i+1)%2;
}
[/code]

所以有可能,Producer一直在生产,而Consumer因为没有获得q对象的monitor,从而没有打印出
[code="java"]
System.out.print(q.name);
System.out.println(":" + q.sex);
[/code]

你在
i=(i+1)%2; 下面加一个 q.wait(); 表示拥有q对象monitor的当前线程等待


System.out.print(q.name);
System.out.println(":" + q.sex);
下面 q.notify(); 表示唤醒一个q对象等待的线程

i=(i+1)%2;
i =0 那么不就永远是0了

实验了一下你的程序,是可以输出lishi的,只不过张三和李四的输出不是相隔输出的。
[code="java"]
if(i==0)
{
q.name="zhangsan";
try{Thread.sleep(1);}catch(Exception e){}
q.sex="male";
System.out.println(i);
}
else
{
q.name="lisi";
q.sex="female";System.out.println(i);
}

i=(i+1)%2;
[/code]

如果else里的输出的话,就可以看到0和1是间隔输出的。

但是 zhangsan 和 lishi的输出不是相隔的,主要是因为Consumer这个线程输出的时候节奏赶的正好有些不一样!

给个例子,不知道这样能不能满足你的需求,消费总会在生产之后执行,但不是生产A,紧接着就消费A:
[code="java"]
/*
*来源: http://eric-619.iteye.com/blog/693681

  • 生产者消费者问题其含义就是先生产出了产品,才能拉出去让消费者购买
  • 一、重点:
  • 1、多个线程数据共享区域化思想!---源于多线程的近亲思想!!(类似于静态变量的改变)
  • (如栈内存和对内存,还有当做栈内存和堆内存,如数组和基本数据类型,只要是访问的同一个。)
  • 2、生产者消费者

  • 二、synchronized加锁:

  • */

public class ProCon{ //主方法

public static void main(String[] args){

SyncStack stack = new SyncStack();

Consumer p = new Consumer(stack);

Producer c = new Producer(stack);

new Thread(p).start();

new Thread(c).start();

}

}

class Producer implements Runnable{ //生产者

private SyncStack stack;

public Producer(SyncStack stack){   
this.stack = stack;   
 }   

public void run(){   
for (int i = 0; i < stack.pro().length; i++){   
String product = "产品"+i;   
stack.push(product);   
System.out.println("生产了: "+product);   
try{   
 Thread.sleep(200);   
 }catch(InterruptedException e)   
  {   
   e.printStackTrace();   
 }   

}

}

}

class Consumer implements Runnable{ //消费者

private SyncStack stack;

public Consumer(SyncStack stack) {

this.stack = stack;

}

public void run(){

for(int i = 0; i < stack.pro().length; i++){

String product = stack.pop();

System.out.println("消费了: "+product);

try{

Thread.sleep(1000);

}catch(InterruptedException e){

e.printStackTrace();

}

}

}

}

class SyncStack{ // 此类是(本质上:共同访问的)共享数据区域

private String[] str = new String[10];

private int index;

public synchronized void push(String sst){ //供生产者调用   
if(index == sst.length()){   
 try{   
  wait();   
 }catch(InterruptedException e){   
   e.printStackTrace();   
  }   
}   

this.notify(); //唤醒在此对象监视器上等待的单个线程

str[index] = sst;

index++;

}

public synchronized String pop(){ //供消费者调用

if(index == 0){

try{

wait();

}catch (InterruptedException e){

e.printStackTrace();

}

}

notify();

index--;

String product = str[index];

return product;

}

public String[] pro(){ //就是定义一个返回值为数组的方法,返回的是一个String[]引用   
 return str;   //这是一个String[]引用   

}

}

[/code]