(四)生产者消费者模式

2023-05-16

(一)生产者消费者模式原理:

在一个系统中,存在生产者和消费者两种角色,他们通过内存缓冲区进行通信,生产者生产消费者需要的资料,消费者把资料做成产品。生产消费者模式如下图:

在这里插入图片描述

(二)代码实现

生产者是一堆线程,消费者是另一堆线程,内存缓冲区可以使用List数组队列,数据类型只需要定义一个简单的类就好。最关键就是内存缓冲区为空的时候消费者必须等待,而内存缓冲区满的时候,生产者必须等待。其他时候可以是个动态平衡:
 
在这里插入图片描述
首先设置Market类:
其中变量有:Max(仓库最大值),List(用于存放数据)
方法有Producer(生产方法),Cost(消费方法)

public class Market{
   private int Max=20;
   private List<String>list=new ArrayList<String>();
   
   public synchronized void producer()throws InterruptedException{             //设置锁
        if(list.size()>=20){
           this.wait():                       //超过容量时,等待
          }
       System.out.println("***开始生产,现在数量为"+list.size()); 
       list.add("a");
       System.out.println("***生产后数量为"+list.size());
          
           this.notify();                 //唤醒线程
       }

  public synchronized void cost()throws InterruptedException{
              if(list.size()<0){
                  this.wait();                     //线程休眠
                  }
              
        System.out.println("开始消费,现在数量为:"+list.size());
        list.remove(0);
        System.out.println("消费后数量为:"+list.size());
           this.notify();                      //唤醒线程
        }
}

其次分别时Producer和Cost类,都要继承Thread类,重写run方法

public class Producer extends Thread{                //继承run方法
   private Market market;
   public Producer(Market market){
       this.market=market;
       }
    public void run(){
       while(true) {
	
			try {
				Thread.sleep(new Random().nextInt(500));     //设置时间延迟
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		try {
			market.production();                              //调用生产方法
		} catch (InterruptedException e) {             
			// TODO Auto-generated catch block
			e.printStackTrace();
		 }
	  }
	}

public class Cost extends Thread{                //继承run方法
   private Market market;
   public Cost(Market market){
       this.market=market;
       }
    public void run(){
       while(true) {
	
			try {
				Thread.sleep(new Random().nextInt(500));     //设置时间延迟
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		try {
			market.cost();                              //调用消费方法
		} catch (InterruptedException e) {             
			// TODO Auto-generated catch block
			e.printStackTrace();
		 }
	  }
	}


最后写出测试类,启动线程

public class Test{
   public static void main(String[]args){
           Market market=new Market();
		Producer p1=new Producer(market);
		Producer p2=new Producer(market);
		Producer p3=new Producer(market);
		
		Cost c1=new Cost(market);
		Cost c2=new Cost(market);
		
		
		
		p1.start();                //启动线程
		p2.start();
		p3.start();
		
		c1.start();
		c2.start();
      }
}

得到的运行结果为:
在这里插入图片描述
可知模拟的生产者消费者模式

(三)代码关键点分析:

1.锁问题:

对于Market中的Producer方法和Cost方法,要使用Synchronized关键字同步非静态方法,且要与wait()方法放在一起,使得在多个消费者生产者线程访问Market中的共享资源时不会发生线程安全问题,并且可以保证锁的时同一个对象

  public synchronized void producer()

  public synchronized void cost ()

2.线程的等待与重启

在生产时达到仓库的最大值后,要停止生产,即让生产的线程处于等待状态,此时需要调用wait()方法,


               if(list.size()>=20){
                  this.wait();                     //线程休眠
                  }

                this.notify();                 //唤醒线程

要用this来调用wait()方法,而不能用list,是因为被加锁的对象this在调用wait()和notify(),加锁的对象调用 wait() 方法后,线程进入等待状态,直到在加锁的对象上调用 notify() 方法来唤醒之前进入等待的线程

3.While循环放置在Producer和Cost类的run方法中:

使用while循环是原因:要保证线程可以一直运行下去:

   public void run(){
       while(true) {
	
			try {
				Thread.sleep(new Random().nextInt(500));     //设置时间延迟
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		try {
			market.cost();                              //调用消费方法
		} catch (InterruptedException e) {             
			// TODO Auto-generated catch block
			e.printStackTrace();
		 }
	  }

如果把while循环放在Market中,则睡眠的线程被唤醒之后有可能不满足while()中的条件判定,使得线程线程无法再调用Market中的producer方法,从而无法唤醒线程,因此要放在线程外

4.时间延迟问题:

若要模拟生产和消费的随机过程,还要设置时间延迟

  public void run(){
       while(true) {
	
			try {
				Thread.sleep(new Random().nextInt(500));     //设置时间延迟
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		try {
			market.cost();                              //调用消费方法
		} catch (InterruptedException e) {             
			// TODO Auto-generated catch block
			e.printStackTrace();
		 }
	  }

放在Producer类中的原因是只有放在run方法中,线程运行时才会具有随机性
否则会发生只有生产达到最大值后才会开始消费

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

(四)生产者消费者模式 的相关文章

  • 深入浅出解析ChatGPT引领的科技浪潮【AI行研&商业价值分析】

    Rocky Ding 写在前面 AI行研 amp 商业价值分析 栏目专注于分享AI行业中最新热点 风口的思考与判断 也欢迎大家提出宝贵的意见或优化ideas xff0c 一起交流学习 x1f4aa 大家好 xff0c 我是Rocky 202
  • 算法工程师从业两年的总结与感悟 |【WeThinkIn出品】

    Rocky Ding 写在前面 WeThinkIn出品 栏目专注于分享Rocky的最新思考与经验总结 xff0c 包含但不限于技术领域 欢迎大家一起交流学习 x1f4aa 大家好 xff0c 我是Rocky 2023年已经过去两个月了 xf
  • 在疯狂三月之后,深入浅出分析AIGC的核心价值 (上篇)|【AI行研&商业价值分析】

    Rocky Ding WeThinkIn 写在前面 AI行研 amp 商业价值分析 栏目专注于分享AI行业中最新热点 风口的思考与判断 也欢迎大家提出宝贵的优化建议 xff0c 一起交流学习 x1f4aa 大家好 xff0c 我是Rocky
  • go的gin框架的性能测试

    最近可能想用用gin框架 xff0c 刚好在studygolang网站上看到一篇文章 xff0c 一个小伙测试gin的性能 所以想看看性能 我想把php xff0c 原生的golang的http包 xff0c gin框架一起在本地做个测试
  • 如何修改windows server 2016系统用户的密码

    558idc com运维教程之如何修改windows server 2016管理员帐号的密码 自由互联原创视频教程 建议在 1920 1080 分辨率下全屏观看 您也可以下载本视频 Windows server 2016管理员密码的修改和s
  • 传统深度学习在智慧交通中的那些事儿|【人人都是算法专家】

    Rocky Ding 公众号 xff1a WeThinkIn 写在前面 人人都是算法专家 栏目专注于分享AI行业中业务 竞赛 研究 产品维度的思考与感悟 欢迎大家一起交流学习 x1f4aa 大家好 xff0c 我是Rocky 时代的车轮滚滚
  • 转:android开发笔记之设置(settings)DB数据库

    https blog csdn net hfreeman2008 article details 21603577 在设置 settings 应用中 xff0c 我们可以把一些值 int boolean string 保存在db数据库 这个
  • BaseAdapter

    Person 类 xff1a lt span style 61 34 font size 18px 34 gt package com xh tx bean public class Person private Integer id pr
  • QQ 添加分组 添加好友

    package com example qq import java util ArrayList import java util HashMap import java util List import java util Map im
  • 百度地图定位指针

    MainActivity package com example baidumap import com baidu location BDLocation import com baidu location BDLocationListe
  • 微信 未读 置顶 删除 的简单实现

    微信 未读 置顶 删除 的简单实现 xff1a package com example meun import java util ArrayList import android app ListActivity import andro
  • Android仿大众点评

    Android一个仿大众点评的开源项目 xff0c 其在github上的项目主页 xff1a https github com zhangphil FangDaZhongDianPing 该项目只实现了基本的UI界面部分 xff0c 内容部
  • 横竖屏显示 图片分辨率

    1 设置屏幕的横竖屏显示 xff1a 如果不做特殊说明 xff0c 开发的应用是横竖屏重力敏感的 xff0c 如果禁止横竖屏切换 xff0c 需要在AndroidManifest xml文件中做相应的修改 xff1a lt activity
  • IllegalStateException异常解决

    最近在使用response sendRedirect 时出现如下错误 java lang IllegalStateException org apache catalina connector ResponseFacade sendRedi
  • Github第三方登录

    第三方登录的定义 所谓的第三方登录 xff0c 就是利用用户在第三方平台上已有的账号来快速完成自己应用的登录或者注册的功能 而这里的第三方平台 xff0c 一般是已经有大量用户的平台 xff0c 如国内的新浪微博 QQ空间 xff0c 外国
  • java并发之通过线程工厂创建线程

    通过线程工厂创建线程 ThreadFactory接口的Thread newThread Runnable r 方法 package chapter1 import util Sleeper import java util concurre
  • 日历签到

    知识点 xff1a GridView的使用 SQLite的使用 涉及文件 xff1a res gt layout gt activity main xml 主布局文件 res gt layout gt date xml 布局文件 src g
  • GridView布局

    如果是列表 xff08 单列多行形式 xff09 的使用ListView xff0c 如果是多行多列网状形式的优先使用GridView lt xml version 61 34 1 0 34 encoding 61 34 utf 8 34
  • iOS 卡住在 Cloning spec repo 'cocoapods' from 'https://github.com/CocoaPods/Specs.git'

    1 概况 一般是第一次安装cocoapod后 使用pod install 或者 pod update等时候 终端显示 Cloning spec repo 39 cocoapods 39 from 39 https github com Co
  • Apple Developer App 出现 未知错误 的解决办法

    问题场景 部分开发者账号续费前需要下载developer App 来认证信息后才可完成续费在 34 我的 34 内登录后开始认证 点击继续loading一会后弹窗未知错误打电话问Apple客服 说不确定原因 解决办法 下列方法挨个尝试 均有

随机推荐

  • 什么是区块链之简单直白解释

    先看一下比较官方的释义 区块链是分布式数据存储 点对点传输 共识机制 加密算法等计算机技术的新型应用模式 区块链 xff08 Blockchain xff09 xff0c 是比特币的一个重要概念 xff0c 它本质上是一个去中心化的数据库
  • VSCode 代码自动对齐快捷键

    Mac Shift 43 Option 43 F Windows Shift 43 Alt 43 F
  • Error running ‘__rvm_make -j8‘ 错误处理(Mac M1 BigSur)

    安装rvm时出现的坑 xff0c 执行下面install 2 6 6 rvm install span class token number 2 6 span span class token punctuation span span c
  • mac Vim/Vi Insert模式 ESC 按键无效的解决办法

    问题描述 进入Insert 模式 编辑完成 xff0c 习惯性按 esc键退出编辑 xff0c 一直不好使 xff0c 各种组合键 43 Esc统统不好使 解决方案 xff1a ctrl 43 c
  • git reset 的灵活应用

    git reset 常用有三种方式 xff1a 方式影响说明git reset soft只回退 commit 操作影响最小 xff0c 重新 commit 即可git reset mixed回退 commit 和 add 操作默认方式 xf
  • Mac 连接显示器,外接显示器不出影像

    1 现象 转换头 xff0c 连接线已正确连接 xff1b 显示器电源等也亮 xff0c 且是已有视频信号的状态 xff1b 查看设置 显示器 xff0c 里面也显示识别出已连接外接显示器 2 解决办法 显示器支持的 最高刷新率 与 系统设
  • idea多模块打包

    多模块打包的办法有两个 1 在parent的pom下执行deploy 这样就会自动将父 pom以及子 module都发布到仓库 在模块中添加如下选项 lt distributionManagement gt lt repository gt
  • Xcode 模拟器如何录屏

    1 touch bar 录制图标 有touch bar的MacBook xff0c 模拟器为当前最前窗口事 xff0c touch bar 上点击录制图标即可 xff1b 2 快捷键 选中模拟器界面 xff0c command 43 R 3
  • iOS 组件中设置文件支持MRC

    1 设置该文件的Compiler Flags 为 fno objc arc 使用cocopods 加载此组件时 xff0c 在 Pods 下的 Build Phases 中的 Compile Sources目录中 找到想要设置的文件 xff
  • Null passed to a callee that requires a non-null argument 【iOS常见报错收集】

    1 问题描述 xff1a xcode提示如下 xff1a 2 问题原因 此处某参数未设置 Nullable xff0c 但是赋值了nil xff0c xcode自动提示防止nil导致异常 xff1b 3 解决办法 将此处有可能传入nil的参
  • win10扩展EFI分区

    Win10扩展EFI分区 由于需要在Win10上安装Ubuntu18 04双系统 xff0c 硬盘格式为GPT xff0c 安装过程中需要将Ubuntu的引导分区设置Win10的EFI分区 xff0c 但是win10的EFI分区装系统时默认
  • 桌面图标美化,图包分享

    图标修改教程 先放效果图 xff1a 直接进入正题 xff1a 此电脑 网络 回收站等 xff1a 桌面右键 gt 个性化 gt 主题 gt 相关的设置 gt 桌面图标设置 应用等 xff1a 右键应用 gt 属性 系统图标 xff0c 以
  • Spring注解原理的详细剖析与实现

    一 注解的基本概念和原理及其简单实用 注解 xff08 Annotation xff09 提供了一种安全的类似注释的机制 xff0c 为我们在代码中添加信息提供了一种形式化得方法 xff0c 使我们可以在稍后某个时刻方便的使用这些数据 xf
  • Java实现集合的组合(从组合中取出K个元素进行组合的所有情况)

    1 利用递归进行取出数据 span class hljs keyword public span static span class hljs subst lt span T span class hljs subst gt span sp
  • 浅谈Dockerfile文件

    DockerFile dockerfile是用来构建Docker镜像的构建文件 xff0c 是由一系列命令和参数构成的脚本 DockerFile构建过程解析 Dockerfile内容基础知识 每条保留字指令都必须为大写字母且后面要跟随至少一
  • Java基础学习 100 问

    Java基础学习 100 问 来源 xff1a 赢在面试 xff08 Java知音 javascript void 0 x1f609 xff09 一 Java基础篇 1 一个 34 java 34 源文件中是否可以包括多个类 xff08 不
  • Windows下误删EFI分区重建引导简单教程

    环境 xff1a windows10 xff0c 其余环境未经测试 EFI百度词条解释如下 xff1a EFI system partition ESP xff0c EFI 系统分区通常指数据存储介质中的一个分区 xff0c 通常用于硬盘或
  • maven导入本地jar包

    最近看 https github com junicorn kira 实现的java的代码 有个库发现没法使用maven安装 https mvnrepository com artifact com bladejava blade kit
  • TensorFlow入门教程(23)将图像超分辨率模型SRGAN移植到安卓APP(下)

    作者 xff1a 韦访 博客 xff1a https blog csdn net rookie wei 微信 xff1a 1007895847 添加微信的备注一下是CSDN的 欢迎大家一起学习 1 概述 上一讲我们将SRGAN模型由HDF5
  • (四)生产者消费者模式

    xff08 一 生产者消费者模式原理 xff1a 在一个系统中 xff0c 存在生产者和消费者两种角色 xff0c 他们通过内存缓冲区进行通信 xff0c 生产者生产消费者需要的资料 xff0c 消费者把资料做成产品 生产消费者模式如下图