Fork me on GitHub

线程通信中的生产者与消费者模型

生产者与消费者模型——线程通信

利用缓冲区解决:管程法


生产者与消费者模型中主要包含:生产者、消费者、产品、缓冲区四个部分
顾名思义:

  • 生产者负责向缓冲区中投入产品
  • 消费者负责向缓冲区中取出产品
  • 产品(乖乖做自己就好了)
  • 缓冲区是模型中的核心部分
    缓冲区中主要有容器,以及向容器中添加或取出产品的方法,方法(加了synchronized锁)中处理数据,并且负责线程之间的通信。

具体流程看代码:

//生产者、消费者、产品、缓冲区
public class TestPC {
    public static void main(String[] args) {
        //实例化一个容器
        SynContainer synContainer = new SynContainer();
        //生产者
        new Producer(synContainer).start();
        //消费者
        new Consumer(synContainer).start();

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("剩余chicken:"+synContainer.count);
    }
}
//生产者
class Producer extends Thread{
    //获得容器
    private SynContainer container;
    public Producer(SynContainer container){
        this.container=container;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            container.push(new Chicken(i));
        }
    }
}
//消费者
class Consumer extends Thread{
    //获得容器
    private SynContainer container;
    public Consumer(SynContainer container){
        this.container=container;
    }
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                container.pop();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
//产品
class Chicken{
    int id;//产品编号

    public Chicken(int id) {
        this.id = id;
    }
}
//缓冲区
class SynContainer{
    //需要定义一个容器大小
    Chicken[] chickens=new Chicken[20];
    int count=0;//计数器(数组当前下标)

    int i=1;//记录生产第几只鸡
    int j;//记录消费第几只鸡
    //生产者放入产品
    public synchronized void push(Chicken chicken){
        //如果容器已满,则生产者等待
        if (count==chickens.length){
            try {
                System.out.println("容器已满");
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //容器未满则生产
        chickens[count]=chicken;
        System.out.println("生产了第-->"+(i++)+"只鸡--pc-->"+count);
        j=i-1;//给消费第几只鸡赋值(从最后一只开始消费)
        count++;
        //通知消费者消费
        notifyAll();
    }
    //消费者取出产品
    public synchronized Chicken pop() throws InterruptedException {
        //如果容器为空则等待
        if (count==0){
            System.out.println("容器已空");
            this.wait();
        }
        //不为空则消费
        count--;//因为在生产时最后将count++。其实count指向当前数组中最后一个元素位置的下一个位置,所以消费时先count--,就指向了最后一个元素
        Chicken chicken = chickens[count];
        System.out.println("--消费了第-->"+(j--)+"只鸡--cc-->"+count);
        //通知生产者生产
        notifyAll();
        return chicken;
    }
}

运行结果:

注意:

  • pc表示生产者当前在数组中所投产品的下标位置
  • cc表示消费者当前在数组中所取产品的下标位置
posted @ 2020-12-23 16:37  雾深  阅读(114)  评论(0编辑  收藏  举报