等待与唤醒案例
综合使用线程的条件对象和同步代码块来实现线程安全。
以买卖包子为案例,顾客买包子,有则直接吃,没有包子则需等待制作包子,包子铺中有顾客需要包子并且包子库没包子则需制作,没顾客需要包子不制作包子。
很明显有顾客线程以及包子铺线程,通过同步代码块对两个线程实现同步控制。
包子类,设置包子的属性
BaoZi.java
get、set方法已省略
public class BaoZi {
private String pi;
private String xian;
private Boolean state;
public BaoZi(String pi, String xian, Boolean state) {
this.pi = pi;
this.xian = xian;
this.state = state;
}
public BaoZi() {
}
}
包子铺类,生产包子
public class BaoZiPu extends Thread{
private BaoZi bz;
private int count=0;
public BaoZiPu(BaoZi bz) {
this.bz = bz;
}
@Override
public void run() {
// 一直生产包子
while(true) {
// 利用同步代码块来实现和吃货线程间的同步
synchronized (bz) {
// 如果有包子,进入等待状态
if (bz.getState()) {
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 没包子,生产包子
// 生产两种口味的包子
if(count%2==0) {
// 生产大葱韭菜陷包子
bz.setPi("薄皮");
bz.setXian("大葱韭菜");
} else {
// 生产腰子卤肉陷包子
bz.setPi("厚皮");
bz.setXian("腰子卤肉");
}
System.out.println("顾客,您的"+bz.getPi()+bz.getXian()+"包子正在制作");
try {
sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("您的"+bz.getPi()+bz.getXian()+"包子已经做好");
count++;
// 将包子状态设置为true
bz.setState(true);
// 唤醒吃货线程吃包子
bz.notifyAll();
}
}
}
}
}
顾客类,吃包子
public class ChiHuo extends Thread{
private BaoZi bz;
public ChiHuo(BaoZi bz) {
this.bz = bz;
}
@Override
public void run() {
while(true) {
synchronized (bz) {
if (bz.getState()) {
// 有包子,开吃
System.out.println("开始吃包子");
bz.setState(false);
bz.notifyAll();
} else {
// 没包子,等待状态
try {
bz.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
测试类,开启线程
public class DemoTest {
public static void main(String[] args) {
BaoZi baoZi = new BaoZi("第一个皮","第一个陷",true);
BaoZiPu bzp = new BaoZiPu(baoZi);
bzp.start();
ChiHuo ch = new ChiHuo(baoZi);
ch.start();
}
}