流程:
1:生产者生产商品,如果有商品,不生产,唤醒消费者消费商品;如果没有商品,生产者生产商品,并唤醒消费者消费商品;
2:消费者消费商品,如果有商品,消费商品;如果没有商品,唤醒生产者生产商品,并消费商品;
生产者:
public class Producer implements Runnable{
private Goods goods;
private int x = 0;
public Producer(Goods goods) {
this.goods =goods;
}
@Override
public void run() {
while (true) {
if (x % 2 == 0) {
goods.set("蒙牛牛奶", 4);
} else {
goods.set("伊利牛奶", 3);
}
x++;
}
}
}
消费者:
public class Consumer implements Runnable {
private Goods goods;
public Consumer(Goods goods) {
this.goods = goods;
}
@Override
public void run() {
while (true) {
goods.get();
}
}
}
商品:
public class Goods {
private String name;//商品名称
private int price;//商品价格
private boolean flag; // 商品是否存在的标签
//生产者生产商品 synchronized同步
//set 方法说明:多线程生产者一直重复调用set方法,由于同步(synchronized),只能完成一次调用一次,
//第一次没有商品,就生产商品,完成后,有商品,this.notify()唤醒消费者的this.wait()。
//第二次发现有商品,调动this.wait(),让该方法一直在等待中.直到消费者消费,notify(),唤醒等待,代码继续走下,try-catch后面的代码是生产商品,满足
//消费者消费完后要生产商品.
//
public synchronized void set(String name, int price) {
// 如果有商品,不生产,等待消费者消费
if (this.flag) {
try {
this.wait();//生产者等待,唤醒消费者消费。消费者消费完商品,唤醒生产者,是从这里醒过来的时候.
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果没有商品就生产商品,唤醒消费者消费
// 设置数据
this.name = name;
this.price = price;
// 修改标记
this.flag = true;//有商品
this.notify();//唤醒消费者消费,并同时把方法锁起来,(释放消费者wait的同步锁)
}
//消费者消费商品
// get()方法说明:多线程消费者一直重复调用get方法,由于同步(synchronized),只能完成一次调用一次,
//第一次是没有商品,该方法走this.wait(),方法在等待,直到生产者this.notify()通知,消费者代码才继续走下去
//消费商品,this.notify();唤醒生产者this.wait();
public synchronized void get() {
//如果没有商品就生产商品,唤醒消费者消费
if (!this.flag) {
try {
this.wait();//消费者等待,并唤醒生产者生产商品,生产者生产完商品,唤醒消费者,唤醒的位置是在这里
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 如果有商品就等待消费者消费
// 消费商品
System.out.println(this.name + "---" + this.price);
// 修改标记
this.flag = false;//设置已经消费完商品了
this.notify(); //唤醒生产者生产商品,
}
}
测试:
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
//设置商品
Goods s = new Goods();
//设置生产者
Producer producer = new Producer(s);
//设置消费者
Consumer consumer = new Consumer(s);
//线程类
Thread prodTh = new Thread(producer,"生产者");
Thread conTh = new Thread(consumer,"消费者");
//启动线程
conTh.start();
prodTh.start();
}
}