线程等待与唤醒机制实例
以顾客购买包子,老板制作包子同步进行为例,体现等待与唤醒机制的特点:
1.其中包子类成为了老板与顾客的锁对象,通过调用bun.wait()、bun.notify()方法达到让两个线程等待与唤醒的目的。所以老板与顾客类需要Buns成员变量用于接收锁对象。
2.包子类传递了老板与顾客之间需要传递的消息。
3.因为访问了公共资源Buns,为保证线程安全,在线程执行期间,需要用同步代码块synchronized{}把线程语句包裹起来。
//包子类
public class Buns {
private String surface;//包子皮
private String inner;//包子馅
private int count;//包子数量
private boolean isEmpty;//是否做好
//省略构造方法,Getter/Setter,toString
}
//顾客类
public class Customer implements Runnable{
private Buns bun;//用于接收锁对象
public Customer(Buns bun) {
this.bun = bun;
}
@Override
public void run() {
synchronized (bun){
//顾客点包子
System.out.println("选包子皮:");
Scanner sc = new Scanner(System.in);
bun.setSurface(sc.next());
System.out.println("选包子馅:");
bun.setInner(sc.next());
System.out.println("数量:");
bun.setCount(sc.nextInt());
bun.setEmpty(true);
//点好了,唤醒老板
bun.notify();
//开始等待
while (bun.isEmpty()) {
try {
System.out.println("开始玩手机");
bun.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//被唤醒后吃包子
for (int i = 1; i <= bun.getCount(); i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("吃了第" + i + "个" + bun.getInner() + "馅的包子,好吃");
}
}
}
}
//老板类
public class Boss implements Runnable{
private Buns bun;//用于接收锁对象
public Boss(Buns bun) {
this.bun = bun;
}
@Override
public void run() {
synchronized (bun){
//计时等待,让顾客线程先执行
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
//执行做包子
for (int i = 1; i <= bun.getCount(); i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("使用"+bun.getSurface()+bun.getInner()+"馅做了第"+i+"个包子");
}
bun.setEmpty(false);
//做好唤醒顾客
bun.notify();
}
}
}
//main
public static void main(String[] args) {
Buns bun = new Buns();
new Thread(new Customer(bun)).start();
new Thread(new Boss(bun)).start();
}