java生产者消费者流程图_用java实现生产者和消费者问题

2023-05-16

实验一 生产者和消费者问题

一、实验目的和要求

1)、通过编写程序,掌握基本的同步互斥算法,理解生产者和消费者模型。

2)、了解多线程并发执行机制,线程间的同步和互斥。

3)、学习使用同步对象,掌握相应的API。

二、实验主要内容

编写基础的生产者消费者程序,程序反映了生产者和消费者的工作过程,其中缓冲区只存放一类产品,生产者消费者只对一类产品进行操作。

1、创建生产者和消费者线程

2、生产和消费规则

①系统中有多个生产者,生产者每次只生产一种产品;

②系统中有多个消费者,消费者每次可以消费一个产品;

③生产者与消费者共享一个具有n个缓冲区的缓冲池;

④生产者与消费者互斥使用缓冲池,即某一时刻只允许一个生产者或消费者使用缓冲池。

⑤不允许消费者进程到一个空缓冲池去取产品;也不允许生产者进程向一个已装满产品且尚未被取走的缓冲池中投放产品。

⑥缓冲池不要求是循环环形缓冲区,也不要求一定是顺序访问,生产者可以将产品投放入任意的空缓冲区。

三、实验仪器设备:PC兼容机1台

四、程序流程图

a4c26d1e5885305701be709a3d33442f.png

五、实验源代码

publicclassOSLab1 {

publicstaticvoidmain(String[] args) {

BufferPool bufferPool =newBufferPool();// 新建一个缓冲池对象 bufferPool

Producer producer1 =newProducer("生产者A", bufferPool);// 新建一个生产者对象producer1

Producer producer2 =newProducer("生产者B", bufferPool);// 再新建一个生产者对象producer2

Consumer consumer1 =newConsumer("消费者1", bufferPool);// 新建一个消费者对象consumer1

Consumer consumer2 =newConsumer("消费者2", bufferPool);// 再新建一个消费者对象consumer2

Thread proT1 =newThread(producer1);// 从 producer1对象新建一个生产者线程 proT1

Thread proT2 =newThread(producer2);// 从producer1对象新建一个生产者线程 proT2

Thread conT1 =newThread(consumer1);// 从consumer1对象新建一个消费者线程 conT2

Thread conT2 =newThread(consumer2);// 从consumer2对象新建一个消费者线程 conT2

proT1.start();// 使 proT1线程处于可运行状态

proT2.start();// 使 proT2线程处于可运行状态

conT1.start();// 使 conT1线程处于可运行状态

conT2.start();// 使 conT2线程处于可运行状态

}

}

classBufferPool {

String[]buf;// 字符串数组作为内部存储结构

intfront,rear;// 队头指针和队尾指针

intsize;// 数组容量,采用循环队列时实际容量为size-1

intcount= 0;// 创建缓冲区,用来放产品

publicBufferPool() {// 默认构造方法

this(10);// 调用其他构造方法

}

publicBufferPool(intsize) {// 指定容量的构造方法

this.size= size;// 数组容量

buf=newString[size];// 创建数组

front= 0;// 队头指向数组第0个元素

rear= 0;// 队尾指向数组第0个元素

}

// 向缓冲池投放产品

publicsynchronizedvoidputItem(Producer pro, String message) {

while((rear+ 1) %size==front)// 队列为满

{

System.out.println("仓库已满, "+ pro.getProducerName() +"正等待生产...");

try{

this.wait();// 队列为满时,线程运行到此,将进入等待状态

}catch(InterruptedException e) {

System.out.println("BufferPool中出现了异常!");

}

}

buf[rear] = message;// 放入一个产品

rear= (rear+ 1) %size;// 队尾指针后移

count++;// 计数器加1

System.out.println(pro.getProducerName() +" 生产了 1个产品, 库存为"+count);

notifyAll();// 唤醒等待的线程

}

// 从缓冲池取走产品

publicsynchronizedString getItem(Consumer con) {

while(rear==front) {// 队列为空

try{

System.out.println("仓库数量不足, 消费者等待消费...");

this.wait();// 队列为空时,线程运行到此,将进入等待状态

}catch(InterruptedException e) {

System.out.println("BufferPool中出现了异常!");

}

}

String Item =buf[front];// 从缓冲区读取一条消息

front= (front+ 1) %size;// 队头指针后移

count=count- 1;// 计数器减1

System.out.println(con.getConsumerName() +" 消费了 1个产品, 库存为"+count);

notifyAll();// 唤醒等待的线程

returnItem;// 返回产品

}

}

// 定义生产者线程

classProducerimplementsRunnable {

privateStringproducerName=null;

privateBufferPoolbufferPool=null;

// 声明生产者要放产品的缓冲池

publicProducer(String producerName, BufferPool bufferPool) {

this.producerName= producerName;

this.bufferPool= bufferPool;

}

publicvoidsetProducerName(String producerName) {

this.producerName= producerName;

}

publicString getProducerName() {

returnproducerName;

}

// 定义一个新线程必须重写父类的run方法

publicvoidrun() {// 线程的执行体

intcount = 0;// 产品的编号

while(true) {

String Item =producerName+"生产的第"+ (++count) +"个产品";

// 放入缓冲池,如果缓冲区满,当前线程进入等待状态

bufferPool.putItem(this, Item);

try{

Thread.sleep((int) (Math.random() * 2500));// 定义线程休眠时间

}

// 有可能抛出异常,必须对它进行捕捉

catch(InterruptedException e) {

System.out.println("Proceducer中出现了异常!");

}

}// End while

}

}

// 定义消费者线程

classConsumerimplementsRunnable {

publicStringconsumerName=null;

publicBufferPoolbufferPool=null;

// 声明消费者要放产品的缓冲池

publicConsumer(String consumerName, BufferPool bufferPool) {

this.consumerName= consumerName;

this.bufferPool= bufferPool;

}

publicvoidsetConsumerName(String consumerName) {

this.consumerName= consumerName;

}

publicString getConsumerName() {

returnconsumerName;

}

publicvoidrun() {// 线程的执行体

while(true) {

// 从缓冲区取走一个产品,如果缓冲区为空,当前线程进入等待状态

String Item =bufferPool.getItem(this);

if(Item !=null) {

System.out.println("Namely,"+consumerName+"消费了"+ Item

+".");// 取走产品

try{

Thread.sleep((int) (Math.random() * 5000));// 定义线程休眠时间

}catch(InterruptedException e) {

System.out.println("Consumer中出现了异常!");

}

}

}// End while

}

}

六、实验结果

a4c26d1e5885305701be709a3d33442f.png

a4c26d1e5885305701be709a3d33442f.png

七、实验心得

虽然在本实验上花费了不少时间,但通过查阅资料后,最终还是完成了实验要求。本实验虽没有像C++语言那样采用原语操作,但通过wait()、notifyAll和synchronized关键字的配合使用,也还是实现了进程同步与互斥。

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

java生产者消费者流程图_用java实现生产者和消费者问题 的相关文章

  • Qt实现串口通信总结

    Qt实现串口通信总结 注意 xff1a Qt5发布之前 xff0c Qt实现串口通信一般是采用第三方类库qextserialport Qt5发布后自带了QtSerialPort 能够支持串口通信 1 Qextserialport类介绍 在Q
  • 开发中状态到底用数字还是字符串

    做了这么多年网站发现 xff0c 一个遗留下来的习惯是否需要变变 就是在设计数据库及数据结构的时候 xff0c 我们已经习惯了用数字来表示 xff0c 例如 xff1a 0表示正常 xff0c 1表示删除 但是 xff0c 这么设计有几个好
  • org.springframework.expression.spel.SpelEvaluationException: EL1011E: Method call: Attempted to call...

    前言 本文中提到的解决方案 xff0c 源码地址在 xff1a springboot thymeleaf xff0c 希望可以帮你解决问题 至于为什么已经写了一篇文章thymeleaf模板引擎调用java类中的方法 xff0c 又多此一举的
  • (Access denied for user 'root'@'slaver1' (using password: YES))

    1 问题描述 xff0c 启动azkaban的时候报如下所示的错误 之前使用azkaban是root用户 xff0c 今天使用hadoop用户进行配置和使用 xff0c 报这个错 xff0c 说是root连接mysql拒绝了 1 hadoo
  • 【Python实战】用代码来访问1024网站

    1024是一个好网站 首先 xff0c 此次实战系列的前提是您能科学的找到1024网站 xff01 我这里并不提供网站地址 xff0c 特此声明 xff0c 这里只是用计算机科学的态度和方法 xff0c 来分析一个问题 和1024网站没有任
  • js立即执行函数与分组操作符()的用法

    一 圆括号运算符 圆括号运算符也叫分组运算符 xff0c 它有两种用法 xff1a 如果表达式放在圆括号中 xff0c 作用是求值 xff1b 如果跟在函数后面 xff0c 作用是调用函数 把表达式放在圆括号之中 xff0c 将返回表达式的
  • 开开心心做几道JavaScript机试题 - 02

    前集回顾 我们在开开心心做几道JavaScript机试题 01中吐了槽 xff0c 也顺势展开了机试题之旅 xff0c 本章我们暂时压抑自己的吐槽之心 xff0c 继续就题目前行 仍然希望对各位正确认识JavaScript这门语言 xff0
  • 汇总路由的计算方法

    路由汇总的计算 路由汇总计算实例 xff1a 路由表中存储了如下网络 xff1a 172 16 1 0 24 172 16 2 0 24 172 16 3 0 24 172 16 4 0 24 172 16 5 0 24 要计算路由器的汇总
  • Linux 杀死进程方法大全(kill,killall)

    杀死进程最安全的方法 是单纯使用kill命令 xff0c 不加修饰符 xff0c 不带标志 首先使用ps ef命令确定要杀死进程的PID xff0c 然后输入以下命令 xff1a kill pid 注释 xff1a 标准的kill命令通常都
  • 在python中创建对象(object)

    该系列文章 xff1a python入门 xff0c 编程基础概念介绍 xff08 变量 xff0c 条件 xff0c 函数 xff0c 循环 xff09 python中的数据类型 xff08 list xff0c tuple xff0c
  • python 有4个数字1234,能组成多少个互不相同且无重复的三位数数字。

    1 def output 2 count 61 0 3 for i in range 1 5 4 for j in range 1 5 5 for k in range 1 5 6 if i 61 61 j or i 61 61 k or
  • 解决java.net.ConnectException: Connection timed out: connect报错

    使用华为OMF开放实验室定向加速解决方案API时 xff0c 运行TestQosApply类 xff0c http developer huawei com ict cn doc site omf development process z
  • 文件加密技术一例

    文件加密技术一例 给文件加密的技术很多 其中又分为不同等级 以适合不同场合的需要 这里给出最简单的文件加密技术 即采用文件逐字节与密码异或方式对文件进行加密 当解密时 只需再运行一遍加密程序即可 下面是一个实例程序 能对任意一个文件进行加密
  • ERP实务:流程评述之应付帐款流程(转)

    对于ERP项目来说 xff0c 其核心就是企业管理流程 这里我将给大家介绍的第一个流程是应付帐款流程 应付帐款流程说说是一个流程 xff0c 其实 xff0c 根据应付帐款形式的不同 xff0c 其还可以细分为好几个流程 如应付帐款逐笔结转
  • leetcode每日刷题计划-简单篇day15

    leetcode每日刷题计划 简单篇day15 折腾了一圈改出来了二叉树 主要是vector的问题疯狂报错 vector插入直接num i 一直报错空指针 老老实实用a push back 插入内容 xff0c 但是查了一下貌似效率不是很高
  • 大型网站架构系列:20本技术书籍推荐

    学习是技术人员成长的基础 xff0c 本次分享20本技术方面的书籍 xff0c 这些书不是每一本都是经典 xff0c 但是每一本都有其特点 以下20本大部分本人都看过 xff0c 因此推荐给大家 xff08 本次推荐的20本只是一个参考 x
  • 《Microsoft.NET企业级应用架构设计(第2版)》——第2章 为成功而设计 2.1“大泥球”...

    本节书摘来自异步社区 Microsoft NET企业级应用架构设计 xff08 第2版 xff09 一书中的第2章 xff0c 第2 1节 xff0c 作者 xff1a 意 Dino Esposito xff08 埃斯波西托 xff09 A
  • 大气压随温度变化表_物理科普:温度计的发展

    温度计是测温仪器的总称 根据所用测温物质的不同和测温范围的不同 xff0c 有煤油温度计 酒精温度计 水银温度计 气体温度计 电阻温度计 温差电偶温度计 辐射温度计和光测温度计等 最早的温度计是在1593年由伽利略发明的 他的第一只温度计是
  • 联想服务器三角硬盘感叹号,IBM服务器感叹号亮黄灯 无法启动

    1 I 9 14 2016 2 56 19 N 0x4000000e00000000 Remote Login Successful Login ID USERID from Web at IP address 192 168 70 77
  • 用 snprintf / asprintf 取代不安全的 sprintf

    用 snprintf asprintf 取代不安全的 sprintf 在 C 語言裡 xff0c 要建立一個字元陣列的字串 xff0c 常常會使用 sprintf 這個函數來做格式化的處理 但是實際上 xff0c 這個函式卻不是那麼 安全

随机推荐