题外话:从中秋请假到现在,接近20天的假期,让我彻底耍晕了,现在来写代码,发现始终没进入状态。以后建议大家没特殊事情,还是别请这么久啦,分开耍,有利于放松,也不至于耍得忘乎所以。我是一直想做互联网 并发 大数据方面的工作,有兴趣才有动力嘛,企业开发感觉活力不强,太多重复的劳动,还是喜欢研究 解决问题,有挑战的东东。线程这块,生产者与消费者模型一直是很经典的东东,这里我用自己的理解分享一下,有误的地方,还请大家指正哦~。~ 和我有相同发展方向的,可以加个QQ:315040617 一起学习研究哦!
1、解释
从字面上来说,有一个生产者,负责生产产品,当然还有一个消费者,用来消费产品。这个好像很简单啦,假设有一个食品生产厂,然后我来买这些食品(有点废话了)。当然实际情况来看,我不可能专门跑到食品厂区买食品,多麻烦啦,一般情况是食品生产好了,会运送到一个卖食品的地方存放这,比如超市。我们称这样一个地区叫做仓库,那么一个简单的消费模型就诞生了!
2、变化
虽然整个图形很简单,但是变化的情况是很多的,我们大概罗列一下:
a.生产者 产品还没生产出来,仓库是空了,消费者就无法消费,如何处理?
b.生产者 产品生产过多,消费者来不及消费,仓库放不下,如何处理?
c.存在多个消费者,看上了仓库中同一个产品,如何处理?
3.程序设计
下面我们模拟整个操作,来用代码实现,看看效果呢。
3.1 我们先将主体设计出来,肯定有 生产者 ,仓库,消费者 3个对象。
package com; import java.util.Random; /** * * 这是消费者 * */ public class Customer { // 买到的商品数量 private Integer count; // 用户的名字 private String name; public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } public void setName(String name) { this.name = name; } public String getName() { return name; } public Customer(){ // 这里我们用随机 数字,来表示 用户的名字 Random random = new Random(); int num = random.nextInt(100); setName("customer_"+num); } }
package com; /** * * 这是生产者 * */ public class Producer { // 作为生产者,肯定知道生产的数据量 private Integer count;// 产量 public Integer getCount() { return count; } public void setCount(Integer count) { this.count = count; } // 生产产品 public Integer makeProducts(){ // 产品内容我们暂时不关注啦,让数量增加,每单位时间生产1个 return count ++; } }
package com; /** * * 这是一个超市,相当于仓库 * */ public class SuperMarket { // 超市 也需要知道存放的数量 private Integer count; // 超市最大存放的数量 public static final Integer MAX_COUNT = 100; // 肯定有一个卖东西 出去的方法 public void sendProducts(Integer sendNum){ count = count-sendNum; } // 查看超市的目前的产品数量 public Integer getCount(){ return count; } // 同时也有一个存货的方法,给超市添加货物嘛 public void addProducts(Integer count){ this.count = this.count+count; } // 我们要知道是否卖完了 public boolean isEmpty(){ return count <= 0?true:false; } // 同时要知道商品是否放满了,这里我们假设容量是100 public boolean isFull(){ return MAX_COUNT >= 0?true:false; } }
3.2 基本对象有了, 这里我还建立两个维护 生产者和超市,超市和顾客关系的对象。作用是把他们的行为独立出来。并且为了让 我们的生产者 超市 以及消费渠道唯一化,我暂时写死了我们的 类
package com; /** * * 假设这是关系渠道,假设生产者 和超市 只有一个 * */ public class ShareObject { // 主要对象唯一,生产者 和超市 只有一个 public static SuperMarket market = new SuperMarket(); public static Producer producer = new Producer(); // 关系买卖渠道唯一,不存在 da zha qiang(这几个字居然不允许提交) 之类的 public static ProducMarket producAndMarket = new ProducMarket(); public static CustomerMarket customerMarket = new CustomerMarket(); }
package com; /** * * 超市和生产者 之间肯定有联系 * 一般情况有 进货 发货 等操作在这里进行 * */ public class ProducMarket { // 产品交易 public Integer exchange(){ // 看看生产生产了好多产品 Integer total = ShareObject.market.getCount(); System.out.println("生产者生产的产品数量为:"+total); // 超市把产品放进超市 ShareObject.market.addProducts(total); System.out.println("超市现在拥有产品数量为:"+ShareObject.market.getCount()); // 假设生产目前生产的东西全部都送到超市,然后数量就为0了,从新开始生产 ShareObject.producer.setCount(0); return total; } }
package com; import java.util.Random; /** * * 顾客和超市之间肯定有关系嘛, * 这里也是买东西在这里进行 * */ public class CustomerMarket { private SuperMarket market = ShareObject.market; // 顾客买东西 public void buyProducts(){ // 随机表示顾客买东西的数量 Random random = new Random(); int num = random.nextInt(3); // 超市卖出去要少,这么多 market.sendProducts(num); Customer c = new Customer(); System.out.println("顾客:"+c.getName()+" 买走 "+num+" 个产品"); } }
3.3 为了模拟整个操作,对 生产 超市进货 卖出 等,进行了线程管理
package com; /** * * 这是生产者的线程,控制生产这些状态 * 相当于 厂家,需要一个管理晒 * */ public class ProducerThread implements Runnable{ // 生产率,假设1秒生产一个产品(有点快哈~。~) private static final Integer PRODUCT_TIME = 1000; @Override public void run() { // 假设是不间断生产 while(true){ // 工厂开始,开始生产产品 ShareObject.producer.makeProducts(); try { Thread.sleep(PRODUCT_TIME); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package com; /** * * 超市的管理,这个主要负责超市进货 * */ public class SuperMarketAddThread implements Runnable{ // 进货的时间 10秒/次 private static final Integer ADD_PRODUCT_TIME = 10000; @Override public void run() { // 这里我们假设 是24小时运营的超市,按时间进货 while(true){ try { // 进货那个对象操作 ShareObject.producAndMarket.exchange(); Thread.sleep(ADD_PRODUCT_TIME); } catch (InterruptedException e) { e.printStackTrace(); } } } }
package com; /** * * 超市的管理,这个主要负责超市售出 东西 * */ public class SuperMarketSendThread implements Runnable{ // 卖东西出去的时间 1秒 private static final Integer SEND_TIME = 1000; @Override public void run() { // 这里我们假设 是24小时运营的超市 while(true){ try { // 顾客 和超市的类,操作方法 ShareObject.customerMarket.buyProducts(); Thread.sleep(SEND_TIME); } catch (InterruptedException e) { e.printStackTrace(); } } } }
3.4 由于顾客 买东西, 和 超市卖出,我仅让超市 个 顾客的线程处理了,就没专门建立 顾客的线程。
package com; public class Test { /** * @param args */ public static void main(String[] args) { // 生产者 超市 顾客,先让他们存在 Thread producter = new Thread(new ProducerThread()); Thread marketAdd = new Thread(new SuperMarketAddThread()); Thread marketSend = new Thread(new SuperMarketSendThread()); // 顾客的的行为,我在SuperMarketSendThread 维护了 // Thread customer = new Thread(); // 为了初始化,我先假设 生产者 已经生产了 50 产品 // 超市里面 已经进货了 10个产品,不至于为空 ShareObject.producer.setCount(50); ShareObject.market.addProducts(10); // 1. 逻辑上 我们应该先让生产者执行晒,毕竟要先生产产品嘛 producter.start(); // 2.然后是超市 marketAdd.start(); // 3.然后才是消费者 来消费 marketSend.start(); // 虽然这么些,其实执行顺序是随机的。要加入队列才行,留在后面吧 // 上面数量 ,可以将顾客买的数量随机数 改大,容易出现负数 } }
小结:
1.上面是模拟了生产者消费者模型的实现,我们把 生产者,超市唯一化了。而实际情况要复杂很多。上面程序是有BUG的,因为没有考虑各种限制,2.变化 所列出的,都没考虑进去,留在后面进行了。
2.整个程序设计是很初步的,有兴趣的童鞋,可以自己完善,后面我也会将常用的设计模式 融入进去,包括一个宏观设计,更加抽象,体验设计带来的乐趣。
3.有啥批评建议的,尽管说,我脸皮厚,最喜欢大家的各种抨击,才能学习成长!
相关推荐
1.掌握基本的同步互斥算法,理解生产者和消费者模型。 2.了解Windows 2000/XP中多线程的并发执行机制,线程间的同步和互斥。 3.学习使用Windows 2000/XP中基本的同步对象,掌握相应的API。 三、实验要求 1.生产者...
内容概要:基于QT Creator环境的多线程编程验证互斥的原理,通过使用semaphore,mutex等控制变量,实现对生产者消费者模型的真实模拟。...阅读建议:结合代码及相关文档对生产者消费者模型进行理解。
基于Linux C++的条件变量实现的生产者消费者模型,旨在进一步帮助读者理解条件变量的使用。
用MFC编写的生产者消费者经典问题.易懂,好操作.
为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池:生产者进程从文件中读取一个数据,并将它存放到一个缓冲区中; 消费者进程从一个缓冲区中取走数据,并输出此数据。生产者和消费...
上课实验用VC++做的操作系统实验之进程的互斥与同步(生产者与消费者问题),内含实验报告,希望对大家有帮助
本实验所使用的生产者和消费者模型具有如下特点: 本实验的多个缓冲区不是环形循环的,也不要求按顺序访问。生产者可以把产品放到目前某一个空缓冲区中。 消费者只消费指定生产者的产品。 在测试用例文件中指定...
在生产者与消费者之间在加个缓冲区,我们形象的称之为仓库,生产者负责往仓库了进商 品,而消费者负责从仓库里拿商品,这就构成了生产者消费者模型。结构图如下: 生产者消费者模型的优点: 1、解耦 假设生产者和...
理解java中生产者消费者模型,以及如何利用双缓冲机制来解决同步与死锁问题。
读《深入理解计算机系统》后,参照书中程序,用C代码实现生产者消费者模型,本代码可移植性强,各接口以封装好,并有注释
(1)掌握基本的同步互斥算法,理解生产者和消费者同步的问题模型。 (2)了解Windows 2000/XP中多线程的并发执行机制,线程间的同步和互斥。 (3)学习使用Windows2000/XP中基本的同步对象,掌握相应的API。 2、...
使用Java完成的生产者消费者模型,适合初学者对线程进行深入理解使用,本代码仅用于学习交流,祝各位学习顺利!
1、通过编写程序,掌握基本的同步互斥算法,理解生产者和消费者模型。 2、了解多线程并发执行机制,线程间的同步和互斥。 3、学习使用同步对象,掌握相应的函数。
基于Microsoft Visual Studio环境的多线程编程验证互斥的原理,理解多线程编程中关键元素的定义与使用,通过使用Semaphore,mutex等控制元素,实现对生产者消费者模型的真实模拟,函数的功能与实现自己定义。
1.掌握基本的同步互斥算法,理解生产者和消费者模型。 2.了解Windows 2000/XP中多线程的并发执行机制,线程间的同步和互斥。 3.学习使用Windows 2000/XP中基本的同步对象,掌握相应的API。 三、实验要求 1.生产者...
内容概要:这是一个以消费者生产者模型为基础的用队列作为存储的已封装完毕的线程池,内涵了threadpool.c、queue.c等文件 适合人群:对消费者生产者模型有...能学到什么:线程池的工作原理,深入理解消费者生产者模型。
说明:本人在给Java游戏开发特训班讲解多线程时,需要说明多线程同步的问题,其中讲解了使用“生产者-消费者”模型来解决同步问题。可是当时特训班的学生不是很明白,特别是不明白这个模型怎么使用。这可能是由于...
(1) 通过编写程序实现进程同步和互斥,掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的内容。 (2) 了解Windows2000/XP中多线程的...