Java设计模式之消费者模式【小二讲堂】

Java设计模式大全:https://blog.csdn.net/mirror_w/article/category/8845914
在这里插入图片描述
所谓消费者模式如图所示,能理解了什么呢?

一、入门思想

思想: 生产者和消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。而进过阻塞队列(或者缓冲区)来进行通讯。所以生产完不用等待消费者直接放到阻塞队(或者缓冲区)中,消费者不是直接向生产者获取数据而是直接从阻塞队列中获取数据,平衡了消费者和生产者的处理能力,这样就解决了消费者和生产者之间的强耦合问题。

举例:
1、你把信写好——相当于生产者制造数据
2、你把信放入邮筒——相当于生产者把数据放入缓冲区
3、邮递员把信从邮筒取出——相当于消费者把数据取出缓冲区
4、邮递员把信拿去邮局做相应的处理——相当于消费者处理数据
优点:

  • 1.解耦
    当消费者和生产者之间不存在缓冲区或者阻塞队列时,如果生产者直接调用消费者者的方法进行消费资源,这样就形成了依赖(强耦合),当生产者的某些方法或结构发生变化时会直接影响到消费者。当加入缓冲区时,则消费者和生产者互影响(低耦合)
  • 2.支持高并发
    生产者如果直接调用消费者的方法时,如果消费者没有返回方法之前生产者只能一直等待,等待消费者返回才能生产下一批资源,这样等待这段时间,浪费了很大的时间和cpu资源。当加入缓冲区或者阻塞队列时,生产者和消费者不再依赖彼此,这样生产者可以并发生产,消费者可以并发获取
  • 3.支持忙闲不均
    缓冲区还有另一个好处。如果制造数据的速度时快时慢,缓冲区的好处就体现出来了。当数据制造快的时候,消费者来不及处理,未处理的数据可以暂时存在缓冲区中。等生产者的制造速度慢下来,消费者再慢慢处理掉。

二、传输原理

类似与点对点传送,又略有不同,一个生产者可以对应N个消费者,但是一个消费者只能对应一个生产者,每个生产者消费者对应一个地址,占一个网络节点,属于预定性数据,在网络中优先级最高。

由于此模式如果在网络中设置过多会影响网络传输速度,一般用在传输比较重要的信息上,比如设备的启动、停止、故障、急停等等,因为在Controlnet网络中节点数是有限制的,最高节点数为99。

如果两个控制器之前建立了多个生产者消费者的连接,只要一个失败,则所有的均失败。将数据整合到用户自定义结构或数组中 ,两个控制器中只保留一个连接。
生产者消费者信息可以通过以太网和Controlnet传输,但是同时只能通过一种途径传输。 在建立标签时必须建立在全局变量里面,不能建立在局部变量里标签的大小不能超过500B。如果生产者几个数据传输到到同一个控制器的的几个消费者中,将几个数据合并在一个用户自定义标签中,可以减少连接数,但合并后的数据将会会用相同的RPI。
生产者消费者标签只能用DINT和REAL,或它们的数组,或用户自定义结构数据,因为对外操作数据必须是32位的,如果有SINT和INT的数据要传输,必须将它们组合在用户自定义结构中传送,生产者和消费者的标签数据格式必须一致,才能确保数据的准确性,如果数据打包后超过了 32位,那么生产者和消费者双方必须使用一个复制缓冲指令,以获得数据的同步,例如Control Logix中的CPS指令。

如果生产者要发送的32位数据,与非Control Logix的对方设备的数据结构不匹配,例如对方是16位的数据,为避免偏差,改为用户自定义结构。
消费者的 RPI必须大于等于网络刷新时间NUT,如果几个消费者请求同一个生产者,则会以最小最快的RPI为准。

三、案例演示

代码示例:

  • 1.准备一个商品类用于生产者生产和消费者的消费
  • 类说明 :商品类----生产者消费者
public class Product {

	private String brand;// 品牌
	private String name;// 品牌下的名字
	private boolean flag = false;// 商品的状态,flag:true有商品,false:无商品

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	// 消费商品
	public synchronized void getProduct() {
		// 如果没有商品就等待
		if (!flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 进行消费
		System.out.println("消费者消费了:" + this.getBrand() + "---" + this.getName());
		// 消费完之后,将flag置为flase
		flag = false;
		// 唤醒生产者进行生产
		notify();
	}
	// 生产商品
	public synchronized void setProduct(String brand, String name) {
		// 如果有商品就等待
		if (flag) {
			try {
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.setBrand(brand);
		this.setName(name);
		// 有商品就消费
		System.out.println("生产者生产了:" + this.getBrand() + "---" + this.getName());
		// 生产完将flag置为true;
		flag = true;
		// 将消费者唤醒
		notify();
	}
}

创建一个生产者,用于生产商品

public class Producer implements Runnable {

	private Product p;

	public Producer(Product p) {
		this.p = p;
	}

	@Override
	public void run() {
		// 进行生产商品
		for (int i = 1; i <= 10; i++) {
			if (i % 2 == 0) {
				p.setProduct("哈尔滨", "啤酒");
			} else {
				p.setProduct("巧克力", "蛋糕");
			}
		}
	}

}

创建一个消费者用于消费商品

/
 * 
 * @author Xiao er:
 * 
 * @version 创建时间:2019年3月2日 下午1:59:32
 * 
 *          类说明 :消费者进行消费商品----生产者消费者
 */
public class Customer implements Runnable {

	private Product p;

	public Customer(Product p) {
		this.p = p;
	}

	@Override
	public void run() {
		// 消费10个商品
		for (int i = 0; i <= 10; i++) {
			p.getProduct();
		}

	}

}

Java设计模式:https://blog.csdn.net/mirror_w/article/category/8845914
小二讲堂:https://blog.csdn.net/Mirror_w
大数据入门:https://blog.csdn.net/Mirror_w/article/details/89190381

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值