Python Asyncio模块实现的生产消费者模型的方法
作者:mrr 发布时间:2022-02-10 16:13:49
asyncio的关键字说明
event_loop事件循环:程序开启一个无限循环,把一些函数注册到事件循环上,当满足事件发生的时候,调用相应的协程函数
coroutine协程:协程对象,指一个使用async关键字定义的函数,它的调用不会立即执行函数,而是会返回一个协程对象,协程对象需要注册到事件循环,由事件循环调用。
task任务:一个协程对象就是一个原生可以挂起的函数,任务则是对协程进一步封装,其中包含了任务的各种状态
future:代表将来执行或没有执行的任务结果。它和task上没有本质上的区别
async/await关键字:async定义一个协程,await用于挂起阻塞的异步调用接口,在python3.4是使用asyncio.coroutine/yield from
在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时,就需要有一个模型来做匹配(偶合),实现做的包子都会依次消费掉。
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. 运行:首先创建事件循环,然后进入主逻辑,直到完成,关闭循环。
来源:http://www.cnblogs.com/johnthegreat/p/14461803.html


猜你喜欢
- 复数数据结构在 cpython 当中对于复数的数据结构实现如下所示:typedef struct { double
- 很多时候,我们需要对List进行排序,Python提供了两个方法,对给定的List L进行排序:方法1.用List的成员函数sort进行排序
- Hi,好久不见,我还是那颗翻滚的老鼠屎。处理数据时想求两个表格求不相交的部分,或许是对知识的匮乏限制了我的想象力,并未找到直接求的方法,在这
- settings文件中配置:LOGGING = { 'version':1, 'disabl
- 1,查看log情况mysql> show global variables like '%log%';+-------
- 遍历并修改图像像素值在使用opencv处理图像时,有时需要对图像的每个像素点进行处理,比如取反、修改值等操作,就需要通过h和w遍历像素。依然
- 假如有个任务: 给定一个字符串,通过查询字典,来替换给定字符中的变量。如果使用通常的方法:>>> "This i
- 不过,如果您需要查找文档中的一个特定的元素,最有效的方法是 getElementById()。 不过要注意的是使用getElementByI
- 最近学了一点点python爬虫的知识,面向百度编程爬了一本小说之后感觉有点不满足,于是突发奇想尝试爬一本漫画下来看看。一、效果展示首先是我们
- 本文实例讲述了Python lxml模块的基本使用方法。分享给大家供大家参考,具体如下:1 lxml的安装安装方式:pip install
- Select CONCAT( 'drop table ', table_name, ';' ) FROM i
- 数据集数据集为Barcelona某段时间内的气象数据,其中包括温度、湿度以及风速等。本文将简单搭建来对风速进行预测。特征构造对于风速的预测,
- 一、概述 对象是Oracle8i以上版本中的一个新的特性,对象实际是对一组数据和操作的封装,对象的抽象就是类。在面向对象技术中,对象涉及到以
- 首先,需要获取任意知乎的问题,只需要你输入问题的ID,就可以获取相关的页面信息,比如最重要的合计有多少人回答问题。问题ID为如下标红数字编写
- 1、创建存储过程 create or replace procedure test(var_name_1 in type,var_name_
- 遇到两次mysql密码忘记了?最开始干了最傻的事,卸载了重装。现在有一个不用卸载也能把密码设置回来的办法。知识来源于网络,我这里稍加整理,遇
- 前言:在最近做多智能车的控制时,绘制障碍物的时候发现障碍物的图层被路面图层所覆盖,一时不知道怎么解决,其实在用matplotlib.pypl
- 本文实例讲述了thinkphp5.1 框架钩子和行为用法。分享给大家供大家参考,具体如下:行为ThinkPHP中的行为是一个比较抽象的概念,
- MySQL多表查询添加练习表-- 用户表(user)CREATE TABLE `user`(`id` INT AUTO_INCREMENT
- 昨天群里介绍了一个专门帮你PS图片的网站。吐司网。网站在图片的预览处理上有点意思。当鼠标经过图片,显示为处理过的图片。这样大家能很清晰的对比