生产者与消费者模式能够实现两个线程交替执行,进一步深入之后能够实现让线程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();//吃货发现没有包子了,叫厨师去做包子
    }
}

 

以上,因为只有两个线程,所以每次唤醒的都是对方。

当出现多个线程时,就会把出自己外所有线程都唤醒,就会出现问题。