生产者与消费者模式能够实现两个线程交替执行,进一步深入之后能够实现让线程A->B->C->A这个多个线程互相唤醒,形成一个圈。
本篇,我们模拟一个包子铺,厨师线程作为生产者;吃货线程作为消费者。
生产者消费者模式的基本套路
1.生产者与消费判断是否等待的判断条件是相反的
2.生产者线程处理完后,唤醒消费者线程
3.消费者线程处理完后,唤醒生产者线程
生产者消费者模式伪代码
ThreadA(){
while(判断条件){
//生产者与消费的判断条件是相反的
this.wait();
}
//语句块-->会改变判断条件
this.notifyall();
}
ThreadB(){
while(判断条件){
//生产者与消费的判断条件是相反的
this.wait();
}
//语句块-->会改变判断条件
this.notifyall();
}
模拟包子铺,厨师线程为生产者;吃货线程为消费者。
public class Bun {
public static void main(String[] args) {
SteamedBun bun = new SteamedBun();
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
bun.produce();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "厨师").start();//定义了一个厨师线程,生长包子
new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
bun.eat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "吃货").start();//定义了一个吃货线程,吃包子
}
}
class SteamedBun {
private int num = 0;//包子数量
//生产者,包子铺的厨师
public synchronized void produce() throws InterruptedException {
if (num != 0) {
//如果包子数量不等0就等着,厨师不用生产包子
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + "---生产了" + num + "包子---,剩余包子数:" + num);
this.notifyAll();//厨师做好了包子,叫吃货去吃
}
//消费者-->吃包子的吃货
public synchronized void eat() throws InterruptedException {
if (num == 0) {
//如果包子数量等于0吃货就等着厨师做包子,
this.wait();
}
System.out.println(Thread.currentThread().getName() + "---吃了" + num + "包子---,剩余包子数:" + (--num));
System.out.println("吃货叫厨师去做包子");
this.notifyAll();//吃货发现没有包子了,叫厨师去做包子
}
}
以上,因为只有两个线程,所以每次唤醒的都是对方。
当出现多个线程时,就会把出自己外所有线程都唤醒,就会出现问题。