`
greemranqq
  • 浏览: 966175 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论
阅读更多

题外话:从中秋请假到现在,接近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.有啥批评建议的,尽管说,我脸皮厚,最喜欢大家的各种抨击,才能学习成长!

  • 大小: 8.5 KB
  • 大小: 33.6 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics