请问多线程通信的有关问题

   阅读
请教多线程通信的问题
下面这个程序,是想写轮流输出男女信息的程序的,
共享的资源类Person,输入类Input,输出类Ouput,
现在问题是,为什么Input的set()方法,要把else删掉才可以轮流输出?
(或者改成一个if不要else其实也可以轮流输出)
感觉自己基础不过关,但是用一个小程序写了关于if...else的代码,也发现不了问题。
请解答,谢谢。

class Person {
String name;
String sex;
boolean sexFlag = false; // 改变性别的标志位
boolean writenFlag = false; // 是否写入数据的标志位

public synchronized void set(String name, String sex) {
// 如果还没写入,就写入数据,写入后修改标志位为true,然后唤醒在该对象锁上等待的线程
if (writenFlag == false) {
this.name = name;
this.sex = sex;
this.writenFlag = true;
this.notifyAll();
// 如果已经写入了数据,就等待
} else if (writenFlag == true) { // "问题:为什么这里要删去else才正确?"
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public synchronized void read() {
// 如果还没有写入了数据,就等待
if (writenFlag == false) {
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 如果已经写入了数据,就打印,打印后修改标志位,并唤醒在该对象锁上等待的线程
} else if (writenFlag == true) {
System.out.println(this.name + " - " + this.sex);
this.writenFlag = false;
this.notifyAll();
}
}
}

class Input extends Thread { // 输入数据的线程类
Person p;

public Input(Person p) {
this.p = p;
}

@Override
public void run() {
while (true) {
if (p.sexFlag == false) {
p.set("May", "girl");
p.sexFlag = true;
} else if (p.sexFlag == true) {
p.set("汤姆", "男");
p.sexFlag = false;
}
}
}
}

class Output extends Thread {// 输出数据的线程类
Person p;

public Output(Person p) {
this.p = p;
}

@Override
public void run() {
while (true) {
p.read();
}
}
}

class Test2 {
public static void main(String[] args) {
Person p = new Person();
new Input(p).start();
new Output(p).start();
}
}



------解决思路----------------------
其实你想交替输出男女信息的话,在set()方法和read()方法中没必要加那么多if else。。
如下即可:
public synchronized void set(String name, String sex) {
//现在的set()方法既相当于你将else注释掉后的情况,if(..){} else if(..){}语句只会执行if或者else里面的语句,而你将else去掉后就变成了两个if语句
//你原来的代码变成两个if语句后,这两个if里面的代码都会执行
if (writenFlag == false) {
this.name = name;
this.sex = sex;
this.writenFlag = true;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public synchronized void read() {
if (writenFlag == true) {
System.out.println(this.name + " - " + this.sex);
this.writenFlag = false;
this.notifyAll();
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
set()方法中只需要关注标志位为false的情况,既当前未写入数据时写入数据,然后唤醒读取线程读取数据并让写入线程等待。
同理:read()方法中只需关注标注为true的情况,既当前已写入数据后读取数据,然后唤醒写入线程并让读取线程等待。
考虑到你这里的情况,完全可以不用wait()和notifyAll()方法,通过writeFlag标志来控制即可,如下
public synchronized void set(String name, String sex) {
if (writenFlag == false) {
this.name = name;
this.sex = sex;
this.writenFlag = true;
}
}

public synchronized void read() {
if (writenFlag == true) {
System.out.println(this.name + " - " + this.sex);
this.writenFlag = false;
}
}
阅读