说明:第一次执行:r.flag为false,不被wait,进行赋值,mike,nan,再把flag置为true,若此时t1继续拿着执行权,判断if(r.flag)为true,执行r.wait,t1被冻结,同时唤醒了t2(t2不被冻结也可以被唤醒),这时只能执行t2,这时if(!r.flag)为false,不执行,执行输出mike...nan,再把flag置为false,并唤醒t1,这时就算t2拿着执行权,if(!r.flag)为true,t2会被wait,只能执行了t1,t1这时x=1,赋值为丽丽,女女女女女,这时在重复上面的步骤,实现了1中的需求。
14-3,线程间通信-等待唤醒机制-代码优化
上例的代码优化:
class Resource {
//为了保护成员变量,使其私有化,并提供public方法将其对外公开
private String name;
private String sex;
private boolean flag = false;
//同步函数解决线程安全问题
public synchronized void set(String name,String sex) {
if(flag) {
try{
this.wait();
}catch(InterruptedException e) {}
}
//下面的程序调用此函数向里传值,进行赋值操作
this.name = name;
this.sex = sex;
flag = true;
this.notify();
}
public synchronized void out() {
if(!flag) {
try{
this.wait();
}catch(InterruptedException e) {}
}
System.out.println(name + "..." + sex);
flag = false;
notify();
}
}
class Input implements Runnable {
Resource r;
Input(Resource r) {
this.r = r;
}
public void run() {
int x = 0;
while(true) {
if(x == 0) {
//调用set方法赋值
r.set("mike","nan")
} else {
r.set("丽丽","女女女女女");
}
x = (x + 1) % 2;
}
}
}
class Output implements Runnable {
Resource r;
Output(Resource r) {
this.r = r;
}
public void run() {
while(true) {
r.out();
}
}
}
class ResourceDemo {
public static void main(String[] args) {
Resource r = new Resource();
Input in = new Input(r);
Output out = new Output(r);
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
t1.start();
t2.start();
}
}
14-4,线程间通信-多生产者多消费者问题
代码说明:
生产者,消费者,比如说生产烤鸭,消费烤鸭。
单一的生产者和消费者用上例的模式就可以解决,若是多个生产者和多个消费者,则要用下列程序解决。
/*
if判断标记,只有一次,会导致不该运行的线程运行了,出现了数据错误的情况。
while判断标记,解决了线程获取执行权后,是否要运行。
notify只能唤醒一个线程,如果本方唤醒了本方,没有意义。而且while判断标记+notify会导致死锁。
notifyAll解决了本方线程一定会唤醒对方线程的问题。
*/
/*
问题描述:有多个烤鸭店和多个消费者,任何一个烤鸭店生产好一只烤鸭,其中一个消费者就会消费烤鸭。
*/
class Resource {
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name) {
/*
如果这里用if,t0如果挂在try上,再被唤醒将不再进行if判断,若为while,t0如果挂在try上,
再被唤醒将继续判断是否成立。
*/
while (flag) {
try {
this.wait();
} catch(InterruptedException e) {}
}
this.name = name + count;
count++;
System.out.println(Thread.currentThread().getName() + "..生产者.." + this.name);
flag = true;
/*
notify的情况下,若t1,t2,t3都挂了,t0有执行权,那么他可能唤醒t1,这时只有生产者没有消费者。
*/
notifyAll();
}
public synchronized void out() {
while(!flag) {
try {
this.wait();
}catch(InterruptedException e) {}
}
System.out.println(Thread.currentThread().getName() + "..消费者.." + this.name);
flag = false;
notifyAll();
}
}
class Producer implements Runnable {
private Resource r;
Producer(Resource r) {
this.r = r;
}
public void run() {
while(true) {
r.set("烤鸭");
}
}
}
class Consumer implements Runnable {
private Sesource r;
Consumer(Resource r) {
this.r = r;
}
public void run() {
while(true) {
r.out();
}
}
}
class ProducerConsumerDemo {
public static vo