生产者与消费者模式能够实现两个线程交替执行,进一步深入之后能够实现让线程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();//吃货发现没有包子了,叫厨师去做包子 } }
以上,因为只有两个线程,所以每次唤醒的都是对方。
当出现多个线程时,就会把出自己外所有线程都唤醒,就会出现问题。