生产消费设计模式

2023-05-16

生产消费模式

在实际的软件开发过程中,经常会碰到如下场景: 某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象的成为生产者;而处理数据的模块,就成为消费者。

单单抽象出生产者和消费者,还不够算上是生产者/消费者模式。该模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介(类似于商店,生产者生产完供货给商店,商店卖给消费者),生产者把数据放入缓冲区,而消费者从缓冲区取出数据。

生产者消费者的关系如下图所示:

生产者消费者模式的原理描述
1. 生产者仅仅在仓储未满时候生产,仓满则停止生产。
2. 消费者仅仅在仓储有产品时候才能消费,仓空则等待生产。
3. 当消费者发现仓储没产品可消费时,会通知生产者生产。
4. 生产者在生产出可消费产品时,应该通知等待的消费者去消费。

程序实例:
1. 先创建一个库存商品管理类

public class ProductStorage {
    // 最大库存
    public static final int Maximum = 100;
    // 当前库存量
    public static int Currentimun = 50;
    // 库存管理实例
    private static ProductStorage instance;

    private ProductStorage() {
    }

    // 获取单例
    public static ProductStorage getInstance() {
        if (instance == null) {
            instance = new ProductStorage();
        }
        return instance;
    }

    // 生产产品
    public synchronized void product() {
        while (Currentimun >= (Maximum / 2)) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Currentimun++;
        System.out.println("当前线程:" + Thread.currentThread().getName() + "生产了一个商品,当前库存量:" + Currentimun);
        notifyAll();
    }

    // 消费产品
    public synchronized void consume() {
        while (Currentimun <= 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        Currentimun--;
        System.out.println("当前线程:" + Thread.currentThread().getName() + "消费了一个商品,当前库存:" + Currentimun);
        notifyAll();
    }
}
  1. 创建商品生产者模型
//商品生产者模型
public class Producter implements Runnable{

    @Override
    public void run() {
        while(true){
            try{
                Thread.sleep(500);
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            //调用生产方法
            ProductStorage.getInstance().product();
        }
    }
}
  1. 创建商品消费者模型
//商品消费者模型
public class Consumer implements Runnable {

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //调用消费方法
            ProductStorage.getInstance().consume();
        }
    }

}
  1. 最后创建主程序 ,主程序的作用,其实就是启动线程。
public class TestProduct {

    public static void main(String[] args) {
        //启动线程
        Producter p=new Producter();
        Consumer c =new Consumer();
        new Thread(p).start();
        new Thread(c).start();
        /*
        这里代码是使用线程池来启动线程
        ExecutorService pool=Executors.newFixedThreadPool(10);
        pool.submit(p);
        pool.submit(c);
        pool.shutdown();*/
    }

}

生产者消费者模式的优点:
1. 将生产模块和消费模块分隔开,从而降低了程序的耦合,便于程序的扩展和维护。
2. 将生产模块和消费模块的分隔,可使生产模块的运行不再依赖消费模块的执行,由同步改为异步执行并且都可支持并发,从而大大提高了程序的效率。
3. 生产者产生的数据存放在缓冲区中,消费者可以按照自己的逻辑来取出数据处理,从而有效的避免消费模块任务执行负载不均的问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

生产消费设计模式 的相关文章

随机推荐

  • Java获取当前的UTC时间

    Java获取当前的UTC时间 Java获取当前的UTC时间Calendar与TimeZone结论 xff1a 因此想要获取UTC时间可以修改系统默认时区或转换时区修改系统默认时区SimpleDateFormat 转换时区 Instant J
  • springboot+security报错405方法不支持解决方法

    在使用 Spring Boot 和 Spring Security 进行 Web 开发的过程中 xff0c 有时候会遇到 HTTP 错误码为 405 的错误 HTTP 错误码 405 表示 方法不允许 xff0c 也就是客户端请求使用的 H
  • pip 安装faiss 不能用,使用conda安装并使用faiss成功

    pip 安装faiss 安装过程没有报错 xff0c import时候必报错 xff01 xff01 xff01 1 安装cpu版本faiss pip default time 61 1000 install i https pypi tu
  • busybox 网络相关

    busybox 瑞士军刀 包含很多linux unix 平台的有用utilities 比如sh ls cat grep touch chmod chown cp mv vi stat等等等 包括系统常用工具 编辑器 shell 文件操作 文
  • linux glibc2.12到2.14升级

    linux centos glibc 2 12 到 2 14 有些软件可能要求系统的 Glibc 高于某个版本才可以正常运行 如果您的 Glibc 低于要求的版本 xff0c 为了运行这些软件 xff0c 您就不得不升级您的 Glibc 了
  • Ubuntu 开机自定义脚本启动(最全版)

    一 背景 同伴在频繁更新系统环境 xff0c 需要经常使用reboot命令重启 xff0c 但每次重启后端Jar都会停止 xff0c 每次重启都需要手动启动Web后端Jar包 针对此种情况 xff0c 想到了采用开机自动启动Jar包的方法来
  • pycharm 中让python程序暂停的几种方法

    1 input 这种方法不用包含模块 xff0c 因此这也是最常用的一种暂停手段 Python2中的raw input 和input 语句在Python3中已经被合并到input 中 2 os system 34 pause 34 这种方法
  • 关于 Win32API 中的 LoadLibrary

    有人说 反射反射 xff0c 程序员的法宝 这句话一点也没有错 如果能够动态的加载类和方法 xff0c 就等于彻底的解除了类和类 xff0c 方法和方法的耦合 当然 xff0c 这样编译器就无法帮你检查出其中的错误了 xff0c 还是有一定
  • ViewPage+RadioGroup实现Tab切换

    以前写过一篇也是Tab切换的文章 xff0c 当时做安卓一年左右 xff0c 单纯觉得这样能实现功能 xff0c 但是没有注意到性能和代码简洁性的问题 xff0c 文章为 http blog csdn net nzzl54 article
  • 学科前沿技术(高性能计算机)

    高性能计算机 xff1a 二十世纪八 九十年代是高性能计算机丰富多彩的时期 xff0c 各种体系结构的系统争奇斗妍 进入二十一世纪 xff0c 高性能计算机产业逐渐成熟 xff0c 用户面大大扩大 xff0c 技术也不断聚焦 工业界认为 x
  • 异常行为分析模型设计

    本文针对异常访问现状及问题进行简要描述 xff0c 在此基础上提出基于一元线性回归的最小二乘法异常访问分析模型 xff0c 通过该模型解决了异常访问中时间与访问间相关性问题 异常访问是指网络行为偏离正常范围的访问情况 异常访问包含多种场景
  • CSS 参考手册

    CSS 参考手册 CSS 参考手册 CSS 选择器 W3School 的 CSS 参考手册定期通过所有主流浏览器进行测试 CSS 属性 CSS 属性组 xff1a 动画背景边框和轮廓盒 xff08 框 xff09 颜色内容分页媒体定位可伸缩
  • C语言求n的阶乘(n!)

    从键盘输入一个数 xff0c 求出这个数的阶乘 xff0c 即 n 算法思想 首先要清楚阶乘定义 xff0c 所谓 n 的阶乘 xff0c 就是从 1 开始乘以比前一个数大 1 的数 xff0c 一直乘到 n xff0c 用公式表示就是 x
  • Oracle grant all privileges to user

    测试流程 xff1a 解锁HR用户 SQL gt alter user hr account unlock identified by hr User altered 创建一个test用户 SYS 64 orcl11g gt CREATE
  • 《自己动手写Docker》书摘之一: Linux Namespace

    Linux Namespace 介绍 我们经常听到说Docker 是一个使用了Linux Namespace 和 Cgroups 的虚拟化工具 xff0c 但是什么是Linux Namespace 它在Docker内是怎么被使用的 xff0
  • YYText

    特性 API 兼容 UILabel 和 UITextView支持高性能的异步排版和渲染扩展了 CoreText 的属性以支持更多文字效果支持 UIImage UIView CALayer 作为图文混排元素支持添加自定义样式的 可点击的文本高
  • 场景设计:用OOP的思想设计一个生产者消费者的模型

    具体模型如下 xff1a 有若干个消费者 xff0c 每个消费者都可以独立的执行消费任务 xff0c 偶尔会因为某种原因 xff0c 该消费者会不可用 xff0c 这个时候不能在给他分配消费任务了 此外还有大量待消费的生产品 xff0c 每
  • Ubuntu卡死在登录界面进不去的处理方法

    原因是显卡驱动坏了 xff0c 基本上本人的16 04版本动不动就坏一次 xff0c 已经习惯了 xff0c 18 04好像好不少 xff0c 也不知道是不是兼容问题 操作很简单 xff0c 就是卸载掉原来的驱动然后重装就OK了 1 在登录
  • 产品化的理解

    我对产品化的理解 产品化的时机是看业务的需要 xff0c 不管是对前景的落实 xff0c 还是项目转化成产品 xff0c 这些都不是技术人员能考虑的 xff0c 业务的发展和策划 xff0c 如何进行市场细化等如果都由技术人员考虑 xff0
  • 生产消费设计模式

    生产消费模式 在实际的软件开发过程中 xff0c 经常会碰到如下场景 xff1a 某个模块负责产生数据 xff0c 这些数据由另一个模块来负责处理 xff08 此处的模块是广义的 xff0c 可以是类 函数 线程 进程等 xff09 产生数