文档章节

生产者/消费者模式

pan_1308
 pan_1308
发布于 2016/10/27 16:20
字数 995
阅读 312
收藏 0

在实际的软件开发过程中,经常会碰到如下场景:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产生数据的模块,就形象地称为生产者;而处理数据的模块,就称为消费者。 

单单抽象出生产者和消费者,还够不上是生产者/消费者模式。该模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。生产者把数据放入缓冲区,而消费者从缓冲区取出数据。

好处:

1、解耦 

  假设生产者和消费者分别是两个类。如果让生产者直接调用消费者的某个方法,那么生产者对于消费者就会产生依赖(也就是耦合)。将来如果消费者的代码发生变化,可能会影响到生产者。而如果两者都依赖于某个缓冲区,两者之间不直接依赖,耦合也就相应降低了。 

2、支持并发

        使用了生产者/消费者模式之后,生产者和消费者可以是两个独立的并发主体(常见并发类型有进程和线程两种)。生产者把制造出来的数据往缓冲区一丢,就可以再去生产下一个数据。基本上不用依赖消费者的处理速度。其实当初这个模式,主要就是用来处理并发问题的。 

3、支持忙闲不均 
  缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来,消费者再慢慢处理掉。 

代码实例:

/**
 * 苹果
 * @author Administrator
 */
public class Apple {

	private int id;
	private String descFlat;
	private String color;
	
	public Apple(int id, String descFlat, String color){
		this.id = id;
		this.descFlat = descFlat;
		this.color = color;
	}
	
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getDescFlat() {
		return descFlat;
	}
	public void setDescFlat(String descFlat) {
		this.descFlat = descFlat;
	}
	public String getColor() {
		return color;
	}
	public void setColor(String color) {
		this.color = color;
	}

	@Override
	public String toString() {
		return "Apple [id=" + id + ", descFlat=" + descFlat + ", color="
				+ color + "]";
	}
}
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 定义篮子  - 多线程模拟实现生产者/消费者模型
 * @author Administrator
 */
public class Basket {

	BlockingQueue<Apple> queue = new LinkedBlockingQueue<Apple>();
	
	// 生产 苹果  // put方法放入一个苹果,若basket满了,等到basket有位置
	public void produce(Apple apple){
		try {
			queue.put(apple); 
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	// 消费 苹果   // take方法取出一个苹果,若basket为空,等到basket有苹果为止(获取并移除此队列的头部)
	public Apple consume(){
		try {
			return queue.take();
		} catch (InterruptedException e) {
			e.printStackTrace();
			return null;
		}
	}
	
}
/**
 * 定义生产者
 * @author Administrator
 */
public class Producer implements Runnable{

	private int instance;
	private Basket basket;	
	private boolean flat;
	
    public Producer(int instance, Basket basket, boolean flat){
    	this.instance = instance;
    	this.basket = basket;
    	this.flat = flat;
    }
	
	public void run() {
		
		System.out.println("开始初始化生产" + instance + "苹果");
		for(int i=0; i<instance; i++){
			Apple apple = new Apple(i,"描述"+i,"红色");
			basket.produce(apple);
		}
		System.out.println("初始化生产了" + instance + "苹果,完毕");
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
        while(flat){
        	if(basket.queue.size() < instance){
        		System.out.println("库存不足,准备生产了" + instance + "苹果");
        		for(int i=0; i<instance; i++){
        			Apple apple = new Apple(i,"描述"+i,"红色");
        			basket.produce(apple);
        		}
        		System.out.println("已经生产了" + instance + "苹果");
    		}
        	try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
        }
	}
}
/**
 * 消费者
 * @author Administrator
 */
public class Consumer implements Runnable{

    private int instance;
    private Basket basket;
    private boolean flat; 
    
    public Consumer(int instance, Basket basket, boolean flat){
    	this.instance = instance;
    	this.basket = basket;
    	this.flat = flat;
    }
	
	public void run() {
		
		while(flat){
			System.out.println("篮子中苹果数量:" + basket.queue.size());
			if(basket.queue.size() >= instance){
				System.out.println("开始消费....");
				for(int i=0; i<instance; i++){
					Apple apple = basket.consume();
					if(apple != null){
						System.out.println(apple);
					}
				}
				System.out.println("消费....结束");
			}else{
				System.out.println("篮子中 苹果不足...");
				try {
					Thread.sleep(1500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}

}
public class BlockingQueueTest {

	public static void main(String[] args) {
		// 定义一个 篮子
		Basket basket = new Basket();
		
		int instance = 5;
		boolean flat = true;
		
		// 初始化 生产者
		Producer producer = new Producer(instance, basket,flat);
        new Thread(producer).start();
		
		// 初始化 消费者
		Consumer consumer = new Consumer(instance, basket, flat);
		new Thread(consumer).start();
	}
	
}

 

© 著作权归作者所有

共有 人打赏支持
pan_1308
粉丝 5
博文 95
码字总数 58819
作品 0
黄冈
私信 提问
rabbitmq学习记录(六)交换机Exchange-direct

实现功能:一条消息发送给多个消费者 交换机模式:direct 相比于之前的fanout模式,可以进一步的筛选获取消息的消费者。 fanout模式下,只要消费者监听的队列,已经与接收生产者消息的交换机...

人觉非常君
07/20
0
0
并发编程(五)——生产者消费者模式

在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。 为什么要使用生产者和消费者模式 在线程世界里...

whc20011
2016/10/31
34
0
rabbitmq学习记录(五)交换机Exchange-fanout

之前学习的都是一条消息发给一个消费者,下面开始记录如何把一条信息发给多个消费者 这边我们用到了交换机Exchange 交换机模式:fanout 模式特点:生产者把消息发送给Exchange之后,Exchang...

人觉非常君
07/20
0
0
消息队列RabbitMq的五种形式队列

MQ全称为Message Queue,消息队列是系统之间的通信方法; RabbitMQ是开源的,实现了AMQP协议的,采用Erlang(面向并发编程语言)编写的,可复用的企业级消息系统; AMQP(高级消息队列协议)是...

xiaomin0322
05/11
0
0
Java多线程学习(七)

等待/通知模式中最经典的案例当属生产者/消费者模式,此模式有几种变形,但都是基于wait/notify的。 生产者/消费者模式有两种类型:操作值的和操作栈的。下面分别从这两方面来讲解生产者/消费...

kakayang2011
2016/03/07
42
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring源码学习笔记-1-Resource

打算补下基础,学习下Spring源码,参考书籍是《Spring源码深度解析》,使用版本是Spring 3.2.x,本来想试图用脑图记录的,发现代码部分不好贴,还是作罢,这里只大略记录下想法,不写太细了 ...

zypy333
今天
10
0
RestClientUtil和ConfigRestClientUtil区别说明

RestClientUtil directly executes the DSL defined in the code. ConfigRestClientUtil gets the DSL defined in the configuration file by the DSL name and executes it. RestClientUtil......

bboss
今天
17
0

中国龙-扬科
昨天
2
0
Linux系统设置全局的默认网络代理

更改全局配置文件/etc/profile all_proxy="all_proxy=socks://rahowviahva.ml:80/"ftp_proxy="ftp_proxy=http://rahowviahva.ml:80/"http_proxy="http_proxy=http://rahowviahva.ml:80/"......

临江仙卜算子
昨天
11
0
java框架学习日志-6(bean作用域和自动装配)

本章补充bean的作用域和自动装配 bean作用域 之前提到可以用scope来设置单例模式 <bean id="type" class="cn.dota2.tpye.Type" scope="singleton"></bean> 除此之外还有几种用法 singleton:......

白话
昨天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部