zoukankan      html  css  js  c++  java
  • 线程通信中的生产者与消费者模型

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

    利用缓冲区解决:管程法


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

    • 生产者负责向缓冲区中投入产品
    • 消费者负责向缓冲区中取出产品
    • 产品(乖乖做自己就好了)
    • 缓冲区是模型中的核心部分
      缓冲区中主要有容器,以及向容器中添加或取出产品的方法,方法(加了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表示消费者当前在数组中所取产品的下标位置
  • 相关阅读:
    html的输出&,空格,大小于号
    html如何修改hr水平直线的粗细
    LODOP指定window默认打印机和临时默认打印机
    微软面试题: 找出二叉树上任意两个结点的最近共同父结点。
    说说自己对hibernate一级、二级、查询、缓存的理解。
    MySql中添加用户,新建数据库,用户授权,删除用户,修改密码
    修改MySQL的默认密码的四种小方法
    java中Scanner的nextLine()和next()的区别
    JAVA中String字符串比较equals()和equalsIgnoreCase()的区别
    HashMap与HashTable的区别
  • 原文地址:https://www.cnblogs.com/code-xu/p/14179450.html
Copyright © 2011-2022 走看看