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 生产/消费者模型实现过程的更多相关文章

  1. Java生产消费者模型——代码解析

    我们将生产者.消费者.库存.和调用线程的主函数分别写进四个类中,通过抢夺非线程安全的数据集合来直观的表达在进行生产消费者模型的过程中可能出现的问题与解决办法. 我们假设有一个生产者,两个消费者来共同抢 ...

  2. Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型

    Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: ​ ​ ​ 每个对象都对应于一个可称为" 互斥锁&qu ...

  3. Python并发编程04 /多线程、生产消费者模型、线程进程对比、线程的方法、线程join、守护线程、线程互斥锁

    Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线程join.守护线程.线程互斥锁 目录 Python并发编程04 /多线程.生产消费者模型.线程进程对比.线程的方法.线 ...

  4. Python之queue模块以及生产消费者模型

    队列 队列类似于一条管道,元素先进先出,进put(arg),取get() 有一点需要注意的是:队列都是在内存中操作,进程退出,队列清空,另外,队列也是一个阻塞的形态. 队列分类 队列有很多中,但都依赖 ...

  5. Python - Asyncio模块实现的生产消费者模型

    [原创]转载请注明作者Johnthegreat和本文链接 在设计模式中,生产消费者模型占有非常重要的地位,这个模型在现实世界中也有很多有意思的对应场景,比如做包子的人和吃包子的人,当两者速度不匹配时, ...

  6. Linux——多线程下解决生产消费者模型

    我们学习了操作系统,想必对生产消费者问题都不陌生.作为同步互斥问题的一个经典案例,生产消费者模型其实是解决实际问题的基础模型,解决很多的实际问题都会依赖于它.而此模型要解决最大的问题便是同步与互斥.而 ...

  7. JAVA实现生产消费者模型

    前言 最近面试比较多,发现生产消费者模型在各公司面试的过程中问的还是比较多的,记录一下常见JAVA实现生产者消费模型的代码 思路 我们通过三种模式来实现 通过wait和notify 通过Lock和Co ...

  8. Python——Queue模块以及生产消费者模型

    1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...

  9. python生产者消费者模型

    业界用的比较广泛,多线程之间进行同步数据的方法,解决线程之间堵塞,互相不影响. server --> 生产者 client --> 消费者 在一个程序中实现又有生产者又有消费者 ,生产者不 ...

随机推荐

  1. pandas玩转excel-> (2)如何利用pandas读取excel数据文件

    import pandas as pd #将excel文件读到内存中,形成dataframe,并命名为peoplepeople=pd.read_excel('D:/python结果/task2/Peo ...

  2. H5_0015:判断是否是微信加载

        var e = document.createElement("script");     e.src = "https://res.wx.qq.com/open ...

  3. java学习笔记之IO编程—File文件操作类

    1. File类说明 在Java语言里面提供有对于文件操作系统操作的支持,而这个支持就在java.io.File类中进行了定义,也就是说在整个java.io包里面,File类是唯一一个与文件本身操作( ...

  4. 如何与GitHub同步,将本地文件push到到远程仓库

    Run git config --global user.email "you@example.com" git config --global user.name "Y ...

  5. 测试用例与PUCCH

  6. Notepad++ 个人洁癖

    插件: JSON Viewer 可以以树的形式查看JSON,同时可以格式化JSON,增加缩进. NppExport 可以高亮复制 下载地址: https://github.com/chcg/NPP_E ...

  7. Mabitis中的#与$符号区别及用法介绍

    这篇文章主要介绍了Mabitis中的 #{}与   ${} 符号区别,需要的朋友可以参考下 一.介绍 mybatis 中使用 Mapper.xml里面的配置进行 sql 查询,经常需要动态传递参数,例 ...

  8. 题解 AT859 【元素の系統名】

    题目传送门. 介绍一种使用string字符串的方法. \(string\)是\(C++\).\(java\).\(VB\)等编程语言中的字符串,字符串是一个特殊的对象,属于引用类型. \(C++\)标 ...

  9. 如何在MacOS的VScode上安装Python3

    由于MacOS上的VScode默认安装的Python版本是2.7,所以需要我们自己手动安装Python3从Python官网下载最新版本-安装-设置环境变量当然是可行的,但下面要介绍的是另外一种方式:H ...

  10. rest_framework:响应器(渲染器)

    一.作用: 根据用户的请求url或者用户可接受的类型.筛选出合适的渲染组件 用户请求url: http://127.0.0.1:8000/test/?format=json http://127.0. ...