解析python 生产/消费者模型实现过程
1.多线程实现
import threading
import queue
import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(levelname)s -->%(funcName)s at line %(lineno)d: \n %(message)s')
log= logging.getLogger() def producer(q):
for k in range(10):
q.put(k)
logging.info("put %s item into queue "%k)
# block all producer main until consumer get all queue members that put
q.join() def consumer(q):
while True:
"""
if queue been empty and q.get(block=True),
because default block in source code is True ,
queue will bock forever util queue put new item .
"""
item=q.get()
logging.info("get out of %s member of queue "%item) # notify q.join() consumer has get out of member of queue
q.task_done() if __name__ == '__main__':
thread_num=5
# limit max length of queue
q = queue.Queue(maxsize=5)
producers=[threading.Thread(target=producer,args=(q,))]
consumers=[threading.Thread(target=consumer,args=(q,)) for i in range(thread_num)]
# start producer and consumer
for pr in producers:
pr.start()
for cn in consumers:
cn.start()
# block main thread of producer
for p in producers:
p.join()
# block main of consumer
for c in consumers:
c.join() 执行结果:可以看到控制台一直阻塞在那里。由于消费者消费完queue里面所有的成员后queue 变成empty,空队列,由于源码q.get()内置参数block一直为True,当取不到时一直阻塞,那么这就意味着当你block 为True时必须设置结束标志让消费者结束,退出死循环接下来我们
改良一下这个方法:

在生产者生产的时候加入结束标志None告诉消费者拿到None时就break 跳出死循环,结束消费,这样就解决了消费之一直阻塞问题:
在producer主线程join之前添加与线程数目相同的None,让每个thread break 跳出死循环:
import threading
import queue
import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(levelname)s -->%(funcName)s at line %(lineno)d: \n %(message)s')
log= logging.getLogger() def producer(q):
for k in range(10):
q.put(k)
logging.info("put %s item into queue "%k)
# block all producer main until consumer get all queue members that put
q.join() def consumer(q):
while True:
"""
if queue been empty and q.get(block=True),
because default block in source code is True ,
queue will bock forever util queue put new item .
"""
item=q.get()
logging.info("get out of %s member of queue " % item)
if item == None:
logging.info("get None stop consumer from while loop")
break
# notify q.join() consumer has get out of member of queue
q.task_done() if __name__ == '__main__':
thread_num=5
# limit max length of queue
q = queue.Queue(maxsize=5)
producers=[threading.Thread(target=producer,args=(q,))]
consumers=[threading.Thread(target=consumer,args=(q,)) for i in range(thread_num)]
# start producer and consumer
for pr in producers:
pr.start()
for cn in consumers:
cn.start()
# block main thread of producer
for p in producers:
p.join()
# put same number of thread_num None to break thread from consumer while
for i in range(thread_num):
q.put(None)
# block main of consumer
for c in consumers:
c.join()
2019-12-21 20:37:00,206 - INFO -->consumer at line 23:
get out of None member of queue
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 25:
get None mean break
2019-12-21 20:37:00,206 - INFO -->consumer at line 23:
get out of None member of queue
2019-12-21 20:37:00,207 - INFO -->consumer at line 25:
get None mean break
Process finished with exit code 0
结果:正常释放所有线程,但是好像每次线程都要加个标志太麻烦,感觉,能不能有更好的办法呢,当然接着往下看:
改良consumer方法在每次消费队列之前检查队列queue.empty() 是否为True,是就直接break跳出while loop:就不需要每次都加None标志了
import threading
import queue
import logging
logging.basicConfig(level = logging.INFO,format = '%(asctime)s - %(levelname)s -->%(funcName)s at line %(lineno)d: \n %(message)s')
log= logging.getLogger() def producer(q):
for k in range(10):
q.put(k)
logging.info("put %s item into queue "%k)
# block all producer main until consumer get all queue members that put
q.join() def consumer(q):
while True:
"""
if queue been empty and q.get(block=True),
because default block in source code is True ,
queue will bock forever util queue put new item .
"""
if q.empty():break
item=q.get()
logging.info("get out of %s member of queue " % item)
# notify q.join() consumer has get out of member of queue
q.task_done() if __name__ == '__main__':
thread_num=5
# limit max length of queue
q = queue.Queue(maxsize=5)
producers=[threading.Thread(target=producer,args=(q,))]
consumers=[threading.Thread(target=consumer,args=(q,)) for i in range(thread_num)]
# start producer and consumer
for pr in producers:
pr.start()
for cn in consumers:
cn.start()
# block main thread of producer
for p in producers:
p.join()
j结果如下:

解析python 生产/消费者模型实现过程的更多相关文章
- Java生产消费者模型——代码解析
我们将生产者.消费者.库存.和调用线程的主函数分别写进四个类中,通过抢夺非线程安全的数据集合来直观的表达在进行生产消费者模型的过程中可能出现的问题与解决办法. 我们假设有一个生产者,两个消费者来共同抢 ...
- Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型
Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: 每个对象都对应于一个可称为" 互斥锁&qu ...
- Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁
Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...
- Python之queue模块以及生产消费者模型
队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...
- Python - Asyncio模块实现的生产消费者模型
[原创]转载请注明作者Johnthegreat和本文链接 在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时, ...
- Linux——多线程下解决生产消费者模型
我们学习了操作系统,想必对生产消费者问题都不陌生.作为同步互斥问题的一个经典案例,生产消费者模型其实是解决实际问题的基础模型,解决很多的实际问题都会依赖于它.而此模型要解决最大的问题便是同步与互斥.而 ...
- JAVA实现生产消费者模型
前言 最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见JAVA实现生产者消费模型的代码 思路 我们通过三种模式来实现 通过wait和notify 通过Lock和Co ...
- Python——Queue模块以及生产消费者模型
1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...
- python生产者消费者模型
业界用的比较广泛,多线程之间进行同步数据的方法,解决线程之间堵塞,互相不影响. server --> 生产者 client --> 消费者 在一个程序中实现又有生产者又有消费者 ,生产者不 ...
随机推荐
- ubuntu更改mysql配置文件,使其产生日志文件mysql.log
1.打开mysql配置文件,将68,69行的注释取消掉,保存关闭 sudo vim /etc/mysql/mysql.conf.d/mysqld.cnf 2.重启mysql服务 sudo servic ...
- 摇一摇—微信7.0.8版本audio无法自动播放问题
近日有一个项目出现audio无法自动播放,查看原因才发现是微信版本更新为7.0.8版本,需要有交互行为,第一次播放需要用户手动点击一下,无法使用DOM中的play()进行直接播放操作,那怎么办呢? 通 ...
- 蓝桥杯第十届C组试题C
从0开始,从右到左给这些字符串的每一位字母起个名字. 比如:A(1位)A(0位) A(2位)A(1位)A(0位) AA = 27, 可以看成(26 * 1)+ A(1) 因为:字母每经过一个轮回,可就 ...
- R 常用清洗函数汇总
目录 1.which() 2.unique() 3.dplyr包 select() filter() arrange() group_by() mutate() transmutate() summa ...
- Beego模板 循环和判断几个例子
Beego模板 循环和判断几个例子 Beego的前端几乎是另一种语言.一些循环.判断,不细看文档真的做不出来. 0. Beego的View模板语法规则: beego前端(view)统一使用了 {{ 和 ...
- java中堆栈的一些理解备忘
堆:用来存放对象的信息,同一个类存放各自的成员变量,共享对象的方法. 栈:用来保存局部变量的值,包括基本数据类型的值.保存类的实例(堆区对象的引用).保存加载方法的帧. 常量池:包含了一个类型所有的对 ...
- windows10(家庭版)+ laradock 安装踩坑记一记
Docker 安装: 首先我们需要在系统安装 Docker 的免费社区版,官方提供 Windows.Mac 及 Linux 等版本下载:下载地址.下载操作系统对应版本后,按照引导流程安装,最后打开 D ...
- window snmp
https://blog.csdn.net/weixin_30367543/article/details/99923014 https://jingyan.baidu.com/article/e3c ...
- SDOI2010 粟粟的书架 lg2468(可持久化,前缀和)
题面见https://www.luogu.org/problemnew/show/P2468 然后这道题属于合二为一题,看一眼数据范围就能发现 首先我们先考虑50分,二维前缀和维护一下(反正我不记得公 ...
- Python标准库之shutil模块
高级的文件.文件夹.压缩包处理模块. 文件复制 copyfileobj 将文件类对象 fsrc 的内容拷贝到文件类对象 fdst. shutil.copyfileobj(fsrc, fdst[, le ...