【JAVA】设计模式之生产者消费者模式的使用分析

Java并发设计模式:生产者-消费者模式、读写锁模式与线程池模式!| 多线程篇(九) 🏆本文收录于「Java进阶实战」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!! 阅读详情

原文地址:http://blog.chinaunix.net/uid-29140694-id-4107880.html

生产者消费者模式并不是GOF提出的23种设计模式之一,23种设计模式都是建立在面向对象的基础之上的,但其实面向过程的编程中也有很多高效的编程模式,生产者消费者模式便是其中之一,它是我们编程过程中最常用的一种设计模式。
生产者消费者模式是为了解决哪一类问题而产生的呢?在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。单单抽象出生产者和消费者,还够不上是生产者/消费者模式。该模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。生产者把数据放入缓冲区,而消费者从缓冲区取出数据。

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

生产者消费者模式的原理描述:
(1)生产者仅仅在仓储未满时候生产,仓满则停止生产。
(2)消费者仅仅在仓储有产品时候才能消费,仓空则等待。
(3)当消费者发现仓储没产品可消费时候会通知生产者生产。
(4)生产者在生产出可消费产品时候,应该通知等待的消费者去消费。
下面通过一个例子描述下生产者消费者模式的使用。 
1、第一个文件ProductStorage.java

/**
 * 库存商品管理类 
 */
public class ProductStorage {

    /**
     * 最大库存量
     */
    public static final int Maximum = 100;
    
    /**
     * 当前库存量
     */
    public static int Currentimum = 50;
    
    /**
     * 库存管理实例
     */
    private static ProductStorage instance;
    
    private ProductStorage(){}
    
    /**
     * 获取单例
     * @return
     */
    public static ProductStorage getInstance(){
        if(instance == null){
            instance = new ProductStorage();
        }
        return instance;
    }
    
    /**
     * 生产产品
     */
    public synchronized void product(){
        while(Currentimum >= Maximum/2){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Currentimum++;
        System.out.println("当前线程:"+Thread.currentThread().getName() + "--生产者生产了一个商品,当前库存量:"+ Currentimum);
        notifyAll();
    }
    
    /**
     * 消费产品
     */
    public synchronized void consume(){
        while(Currentimum <= 0){
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Currentimum--;
        System.out.println("当前线程:"+Thread.currentThread().getName() + "--消费者消费了一个商品,当前库存量:"+ Currentimum);
        notifyAll();
    }
}


2、第二个文件Producter.java

/**
 * 商品生产者模型
 */
public class Producter implements Runnable {
    
    @Override
    public void run(){
        while(true){
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ProductStorage.getInstance().product();
        }
    }
}

3、第三个文件Consumer.java
 

/**
 * 商品消费者模型
 */
public class Consumer implements Runnable{

    @Override
    public void run() {
        while(true){
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ProductStorage.getInstance().consume();
        }
        
    }
}

4、第四个文件TestMain.java
 

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TestMain {

    public static void main(String [] args){
        startProductThread();
        startConsumThread();
    }
    
    /**
     * 开启生产者线程
     */
    public static void startProductThread(){
        System.out.println("--生产者线程执行开始--");
        int pThreadSize = 10;
        ExecutorService pool = Executors.newFixedThreadPool(pThreadSize);
        for(int i=0;i<pThreadSize;i++){
            Producter productThread = new Producter();
            Thread thread = new Thread(productThread);
            pool.execute(thread);
        }
        System.out.println("--生产者线程执行结束--");
    }
    
    /**
     * 开启消费者线程
     */
    public static void startConsumThread(){
        System.out.println("--消费者线程执行开始--");
        int pThreadSize = 10;
        ExecutorService pool = Executors.newFixedThreadPool(pThreadSize);
        for(int i=0;i<pThreadSize;i++){
            Consumer consumeThread = new Consumer();
            Thread thread = new Thread(consumeThread);
            pool.execute(thread);
        }
        System.out.println("--消费者线程执行结束--");
    }
}


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

手势控制 Python !Leap Motion Python 开发教程 (二) 手势控制 Python !Leap Motion Python 开发教程 (二) 现在进入正题,我来给大家总结一下我在使用 Leap Motion 开发过程中的经验以及学到的东西,其中我会概括以及翻译官方给出的注释,为了让这些注释更加通俗易懂,让大家更好理解。 回顾 在上一篇文章中我们讲了如何配置 Leap Motion 的 Python 2.7 的开发环境,如果您还没有配置好您的开发环境,可以参... 阅读详情

相关推荐

单周期CPU设计【Verilog】

第一章 单周期CPU的设计原理 为实现单周期CPU,本文首先研究了单周期CPU的相关理论和工作原理。本章首先简要介绍单周期CPU的基本概念,然后对CPU的工作原理进行简要分析,以便为单周期CPU的设计和开发提供理论基础。 1.1 单周期CPU概述 中央处理器,即CPU,作为计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。在CPU内部,电平从低到高变化的瞬间称为时钟上升沿,两个相邻时钟上升沿之间的时间间隔称为一个时钟周期。单周期CPU指的是一条指令的执行在一个时钟周期内完成,然后开始下一

醉酒、冰城外 2万+

生产者消费者模式的使用分析

生产者消费者模式并不是GOF提出的23种设计模式之一,23种设计模式都是建立在面向对象的基础之上的,但其实面向过程的编程中也有很多高效的编程模式,生产者消费者模式便是其中之一,它是我们编程过程中最常用的一种设计模式。 生产者消费者模式是为了解决哪一类问题而产生的呢?在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数

AlexWong的专栏 937

TEC 高精度控温算法:实现精准升降温与恒温控制

本文深入解析了TEC高精度控温算法的核心原理与工程实践。针对TEC非线性、时变的特性,算法通过智能状态机实现精准升降温与恒温控制,并详细阐述了参数整定、硬件协同及调试优化的系统性方法,为半导体激光器、PCR仪等高精度温控应用提供了一套完整的解决方案。

weixin_29212867的博客 1011

Java多线程(实现多线程、线程同步、生产者消费者)

概述生产者消费者模式是一个十分经典的多线程协作的模式,弄懂生产者消费者问题能够让我们对多线程编程的理解更加深刻。所谓生产者消费者问题,实际上主要是包含了两类线程:​ 一类是生产者线程用于生产数据​ 一类是消费者线程用于消费数据为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为消费者只需要从共享数据区中去获取数据,并不需要关心生产者的行为Object类的等待和唤醒方法方法名说明。

yqqの博客 626

Quartus (Quartus Prime 18.1)的安装及仿真步骤

前两天做计组的课设需要用到Quartus 这个软件,但安装有点麻烦,在网上搜了很多教程,发现都是旧版本的,最后弄了好半天才把环境搭建好。所以,分享一下它的搭建过程。 因为我不经常用它,所以安装的版本是精简版的其他版本的也应该差不多以下是需要下载的安装包: 准备: Quartus Prime 精简版,最新发布: v18.1 1. QuartusLiteSetup-18.1.0.625-wi...

weixin_41082948的博客 8万+

Vscode远程免密连接Linux虚拟机,并配置C/C++运行环境

目前想要深入学习在Linux,也为了方便编写C/C++程序。Linux的环境里一般自带有c++的编译环境,如果没有安装gcc和g++等编译器也比较便利。但是在虚拟机里用vim编写C++程序又不得劲,因此打算使用vscode远程连接Linux虚拟机进行学习。为了防止自己以后还要再配置,重复踩坑,因此写下这篇博客用做记录。环境:windows11、VMware17、rocky linux9.1 ( 开源的CentOS9 )

m0_56779872的博客 8676

JAVA多线程中的消费者生产者

面试题如何控制线程的执行顺序,生产者消费者问题

maxker的博客 1707

RS485设备联网避坑指南:塔石串口服务器在MODBUS平台中的3个关键配置项

本文针对塔石串口服务器在MODBUS物联网平台接入中的常见问题,详细解析了三个关键配置项:工作模式选择、远程端口与保活机制、寄存器映射与轮询策略。通过对比错误与正确配置案例,帮助工程师避开配置陷阱,实现RS-485设备的稳定、高效联网,提升批量部署的成功率与系统可靠性。

weixin_29281941的博客 404

java多线程并发 : 生产者-消费者模型的三种实现方式

生产者生产数据到缓冲区中,消费者从缓冲区中取数据。 如果缓冲区已经满了,则生产者线程阻塞; 如果缓冲区为空,那么消费者线程阻塞。 方式一:synchronized、wait和notify package day4; //wait 和 notify public class ProducerConsumerWithWaitNofity { public static void main(String[] args) { Resource resource = new Resource

火星男孩的分享空间 3160

MATLAB应用实战系列(四十三)-基于MATLAB的光伏并网系统仿真设计

在Matlab中建立光伏电站接入系统模型,包括光伏发电逆变器及负荷模型等,仿真分析接入点处的电能质量,实现高品质并网运行。 壹 构建太阳能电池模型。 初始化参数如下图所示。 贰 构建MPPT控制模型。 具体封装如下所示: 通过PWM算法实现DC-DC稳步输出最大点。 叁 三、构建直流短距离输电线路。 仿真模型如下图: 通过电容来均衡线路电压,使得线路电压保持可靠性。 肆 通过逆变器变换,使得直流线路转换成...

wenyusuran的专栏 3168

轴承故障诊断领域的论文到底有多水

这个是最让人困惑的,就好像你说自己证明了某个方法更好,但是你却没有交代自己怎么做的,或者说你交代的过程有外行话或者逻辑上的缺陷,但是你就这么给出个结果完事了。由于自己没有足够大的学术交流圈子,为了尽量避免误判,我在原来13篇论文的基础上又读了18篇,这些论文至少都出自中文核心,有一些还有EI的title,事实上近几年能找到的文章也不算多,这些基本能说明问题了。当然,还有更多细节,比如说损失函数你得交代吧,模型超参数得介绍全吧,至少数据集是哪个工况下的得说吧,当你想复现这些论文,关注点在这些地方的时候。

weixin_50642818的博客 3050

Java使用多线程模拟生产者和消费者模型

Java使用多线程模拟生产者和消费者模型

qq_45396088的博客 495

EMD (经验模态分解) 在 C++ 中的实现指南

EMD 是由 Norden E. Huang 等人在1998年提出的一种适用于非线性和非平稳信号的分析方法。对称性:IMF 的上下包络对称。零交叉点:IMF 的零交叉点数量与极值点数量相同或相差一个。本文详细介绍了如何在C++中实现EMD,包括理论背景、算法步骤、代码实现和优化等内容。通过丰富的代码示例和详细的解释,希望能够帮助读者掌握EMD的基本原理,并能够在实际项目中灵活应用。未来,随着信号处理技术的不断发展,EMD及其变种(如EEMD、CEEMDAN等)将继续在各个领域发挥重要作用。

qq_38334677的博客 1748

并发编程中的设计模式

在并发编程的过程中,对于某些特定的问题,一般都有特定的解决方案来处理,就好像是设计模式一样,它们具有通用的模板。可以把这些解决方案称为并发编程中的设计模式。 这篇文章结合《Java源码世界》专题中并发工具类以及多线程的相关文章进行总结,形成的一种并发编程的技巧。 一、线程终止 在多线程开发的时候,经常会用到,在某个线程中,需要去终止另外一个线程,Thread类也提供了终止线程的方法stop(),但在JDK中该方法被标记为@Deprecated,原因就在于该方法做过于暴力。stop()会直接真正杀死进程,如果

sermonlizhi的博客 919

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

生产者消费/单例设计模式/线程协作

死锁。(使用sysnchronized易造成死锁,用线程协作解锁 ) lock。 同步: a.同步实例方法 this b.同步块 指定对象(临界资源)监视器 c.同步静态方法 Class 对象监视器 Class oclz =new Object().getClass(); /** *...

dianhou5755的博客 127

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

多线程编程设计模式(单例,阻塞队列,定时器,线程池)

1.饿汉模式只涉及到变量的读操作,是天然线程安全的;懒汉模式既要读取,又要修改所以会涉及到线程安全问题关于线程安全关于线程等待使用wait的地方有两处,所以schedule方法中的notify操作会唤醒两处的wait优先级队列中存储的元素必须是能够进行比较的,所以任务类MyTimerTask也要能够进行比较,比较的依据是执行时间的远近,可以让MyTimerTask类实现Comparable接口或者使用Comparator来构造比较器进行比较。

Mylvzi的博客 1620

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

探索 Java 同步机制

本文从典型的 Monitor Object 设计模式入手,从一个新的视角,来探讨 Java 语言的同步机制。本文将从两个方面进行阐述:使用 C++ 语言来描述 Monitor Object 设计模式。Java 对于这样一个典型的...

color123456的博客 226

线程之间的通信&线程池&设计模式

概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。比如:线程A用来生成包子的,线程B用来吃包子的,包子可以理解为同一资源,线程A与线程B处理的动作,一个是生产,一个是消费,那么线程A与线程B之间就存在线程通信问题。简单一句话:设计模式就是经验的总结创建型模式:简单工厂模式,工厂方法模式,抽象工厂模式,建造者模式,原型模式,单例模式。(6个)结构型模式:外观模式、适配器模式、代理模式、装饰模式、桥接模式、组合模式、享元模式。(7个)

Cream336的博客 382

学会Java高并发核心编程,轻松拿下双十一

然后结合SimpleMockLock独占锁的释放流程、ReentrantLock的抢锁流程,图文并茂地剖析释放、抢占AQS锁的源码和原理。、线程的基本操作、线程池的核心原理、JUC的线程池架构、4种快捷创建线程池的方法。首先介绍使用显式锁的正确方法、显式锁的分类,然后揭秘CAS可能导致的“总线风暴”和CLH自旋锁,最后从实例出发介绍JUC中的可中断锁和不可中断锁、共享锁与独占锁、读写锁。——原子性问题、可见性问题和有序性问题,阐述JMM的核心原理,揭秘Java内存可见性和volatile关键字的底层知识。

老男孩的架构路 178

Java并发编程实战深入理解线程、锁与线程安全设计模式

而` java.util.concurrent.locks.ReentrantLock `则提供了可中断、公平性等高级特性,且支持尝试加锁(`tryLock()`)。竞争发生时逐步升级为轻量级锁、重量级锁,最终阻塞线程。线程是Java并发编程的基础单元,通过`Thread`类或实现`Runnable`接口启动。2. 线程安全集合:如`ConcurrentHashMap`通过分段锁(Segment)实现高并发读写,`CopyOnWriteArrayList`利用写时复制保证读操作无锁。

MmvlaFos的博客 156

一阶段课堂笔记——线程通信以及生产者与消费者模式

1. 线程通信 JDK1.5之前有三个方法实现线程通信: wait() :线程执行完这个方法进入等待队列(一个锁对应一个等待队列),需要被唤醒 notify():通知唤醒,从等待队列中随机唤醒一个线程 notifyAll():全部唤醒 (例)共用一张银行卡,保证存一笔,再取一笔 class demo { public static void main(String[] arg...

White_yang1的博客 185

征服Android面试官路漫漫(一):线程攻略,夯实基础很重要!

其实很简单就下面这张图,含概了Android所有需要学的知识点,一共8大板块:架构师筑基必备技能Android框架体系架构(高级UI+FrameWork源码)360°Androidapp全方位性能调优设计思想解读开源框架NDK模块开发移动架构师专题项目实战环节移动架构师不可不学习微信小程序混合开发的flutterAndroid学习的资料我呢,把上面八大板块的分支都系统的做了一份学习系统的资料和视频,大概就下面这些,我就不全部写出来了,不然太长了影响大家的阅读。

2401_84149814的博客 1034

wait-notify(JUC)

wait-notify,保护性暂停,join,生产者消费者模式,park

2301_79748665的博客 1459

多线程案例(单例、阻塞队列、生消模型、定时器)

多线程案例

m0_60631323的博客 265

java基础(20)(线程池,等待唤醒机制,voliate关键字,单例设计模式《懒汉模式》《饿汉模式》)

线程之间通信 线程之间的通信? 多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。 为什么要处理线程间通信 多个线程并发执行时, 在默认情况下CPU是随机切换线程的,当我们需要多个线程来共同完成一件任务,并且我们希望他们有规律的执行, 那么多线程之间需要一些协调通信,以此来帮我们达到多线程共同操作一份数据。 如何保证线程间通信有效利用资源 多个线程在处理同一个资源,并且任务不同时,需要线程通信来帮助解决线程之间对同一个变量的使用或操作。 就是多个线程在操作同一份数据时,

qq_41934990的博客 273

Java多线程与并发控制优化

在现代的高性能应用中,Java的多线程编程是提升系统响应速度和吞吐量的核心手段。随着多核处理器的普及和大规模数据处理需求的增加,Java多线程和并发编程逐渐成为开发者必备的技能。然而,在多线程环境下,资源争用、死锁、活锁等问题常常导致程序的不稳定与低效。如何高效地管理并发任务、避免常见的并发问题并优化系统性能,成为了优化多线程应用的关键。本文将深入探讨Java多线程模型的基本概念,介绍线程池的使用,分析锁机制和并发工具类(如。

欢迎来到菜鸟不学编程的博客 691
上一篇: Android消息机制3-Handler(实战)
下一篇: 生产者消费者模式-Java实现
dodod2012
博客等级 码龄15年 244粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值