Python - Asyncio模块实现的生产消费者模型
【原创】转载请注明作者Johnthegreat和本文链接
在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时,就需要有一个模型来做匹配(偶合),实现做的包子都会依次消费掉。
import asyncio class ConsumerProducerModel:
def __init__(self, producer, consumer, queue=asyncio.Queue(), plate_size=6): # the plate holds 6pcs bread
self.queue = queue
self.producer = producer
self.consumer = consumer
self.plate_size = plate_size async def produce_bread(self):
for i in range(self.plate_size):
bread = f"bread {i}"
await asyncio.sleep(0.5) # bread makes faster, 0.5s/pc
await self.queue.put(bread)
print(f'{self.producer} makes {bread}') async def consume_bread(self):
while True:
bread = await self.queue.get()
await asyncio.sleep(1) # eat slower, 1s/pc
print(f'{self.consumer} eats {bread}')
self.queue.task_done() async def main():
queue = asyncio.Queue()
cp1 = ConsumerProducerModel("John", "Grace", queue) # group 1
cp2 = ConsumerProducerModel("Mike", "Lucy", queue) # group 2 producer_1 = cp1.produce_bread()
producer_2 = cp2.produce_bread() consumer_1 = asyncio.ensure_future(cp1.consume_bread())
consumer_2 = asyncio.ensure_future(cp2.consume_bread()) await asyncio.gather(*[producer_1, producer_2])
await queue.join()
consumer_1.cancel()
consumer_2.cancel() if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
生产消费者模型可以使用多线程和队列来实现,这里选择协程不仅是因为性能不错,而且整个下来逻辑清晰:
1. 先定义初始化的东西,要有个队列,要有生产者,要有消费者,要有装面包的盘子大小;
2. 生产者:根据盘子大小生产出对应的东西(面包),将东西放入盘子(queue);
3. 消费者:从盘子上取东西,每次取东西都是一个任务,每次任务完成,就标记为task_done(调用函数)。在这个层面,一直循环;
4. 主逻辑:实例化生产消费者模型对象,创建生产者协程,创建任务(ensure_future),收集协程结果,等待所有线程结束(join),手动取消两个消费者协程;
5. 运行:首先创建事件循环,然后进入主逻辑,直到完成,关闭循环。
以上,欢迎交流!
Python - Asyncio模块实现的生产消费者模型的更多相关文章
- python操作rabbitmq,实现生产消费者模型
		
更多详情参考官方文档:https://www.rabbitmq.com/tutorials/tutorial-six-python.html 参考博客:https://blog.csdn.net/we ...
 - Python之queue模块以及生产消费者模型
		
队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...
 - Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型
		
Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义:    每个对象都对应于一个可称为" 互斥锁&qu ...
 - Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁
		
Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...
 - Linux——多线程下解决生产消费者模型
		
我们学习了操作系统,想必对生产消费者问题都不陌生.作为同步互斥问题的一个经典案例,生产消费者模型其实是解决实际问题的基础模型,解决很多的实际问题都会依赖于它.而此模型要解决最大的问题便是同步与互斥.而 ...
 - Java生产消费者模型——代码解析
		
我们将生产者.消费者.库存.和调用线程的主函数分别写进四个类中,通过抢夺非线程安全的数据集合来直观的表达在进行生产消费者模型的过程中可能出现的问题与解决办法. 我们假设有一个生产者,两个消费者来共同抢 ...
 - JAVA实现生产消费者模型
		
前言 最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见JAVA实现生产者消费模型的代码 思路 我们通过三种模式来实现 通过wait和notify 通过Lock和Co ...
 - Python——Queue模块以及生产消费者模型
		
1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...
 - Python asyncio 模块
		
Python 3.4 asyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持. asyncio的编程模型就是一个消息循环.我们从asyncio模块中直接获取一个EventLo ...
 
随机推荐
- Python爬虫笔记一(来自MOOC) Requests库入门
			
Python爬虫笔记一(来自MOOC) 提示:本文是我在中国大学MOOC里面自学以及敲的一部分代码,纯一个记录文,如果刚好有人也是看的这个课,方便搬运在自己电脑上运行. 课程为:北京理工大学-嵩天-P ...
 - ElasticSearch结合Logstash(三)
			
一.Logstash简介 1,什么是Logstash Logstash 是开源的服务器端数据处理管道,能够同时从多个来源采集数据,转换数据,然后将数据发送到您最喜欢的"存储库"中. ...
 - Codeforces Round #613 (Div. 2) A. Mezo Playing Zoma(逻辑)
			
题意: 给出一个移动序列,可以无效化一些指令,问可以移动到多少不同位置. 思路: 第一印象是统计左右指令数目,后来发现左右指令数目和即字符串长度. #include <bits/stdc++.h ...
 - 2019牛客多校 Round4
			
Solved:3 Rank:331 B xor 题意:5e4个集合 每个集合最多32个数 5e4个询问 询问l到r个集合是不是都有一个子集的xor和等于x 题解:在牛客多校第一场学了线性基 然后这个题 ...
 - 【bzoj 3433】{Usaco2014 Jan} Recording the Moolympics(算法效率--贪心)
			
题意:给出n个区间[a,b),有2个记录器,每个记录器中存放的区间不能重叠.求2个记录器中最多可放多少个区间. 解法:贪心.只有1个记录器的做法详见--关于贪心算法的经典问题(算法效率 or 动态规划 ...
 - Codeforces Round #343 (Div. 2) E. Famil Door and Roads (树形dp,lca)
			
Famil Door's City map looks like a tree (undirected connected acyclic graph) so other people call it ...
 - Codeforces Round #646 (Div. 2)  B. Subsequence Hate  (思维,前缀和)
			
题意:给你一个只含有\(0\)和\(1\)的字符串,每次操作可以将\(0\)改成\(1\)或\(1\)改成\(0\),问最少操作多少次,使得子序列中不含有\(010\)和\(101\). 题解:仔细想 ...
 - Python  Base64编码解码
			
import base64 str = '12345678'.encode('utf8') print(base64.b64encode(str).decode('utf8')) # 编码 接收的参数 ...
 - 通过修改etcd来设置或修改节点flannel子网信息
			
在首次启动flannel服务的时候可以手动指定subnet.env文件,配置所在节点的flannel子网网段,如果不指定配置文件,flannel将自动分配一个子网网段并生成配置文件 /var/run/ ...
 - woj1008feedinganimals2-贪心-网络流
			
title: woj1008feedinganimals2-贪心-网络流 date: 2020-03-07 categories: acm tags: [acm,woj,网络流,贪心] 中等题. 标准 ...