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. Conference deadlines

    1. NLP/IR/DM/ML Conference Deadlines(Updating) Two Principles of Deadlines:1. All deadlines converge ...

  2. H5_0013:CSS特色样式集

    按比例变化,同时又限制最大宽高 ".start-wrap {", " width:40%;", " top: 83.21%;", " ...

  3. Docker最全教程——从理论到实战(十八)

    前言 VS Code是一个年轻的编辑器,但是确实是非常犀利.通过本篇,老司机带你使用VS Code玩转Docker——相信阅读本篇之后,无论是初学者还是老手,都可以非常方便的玩转Docker了!所谓是 ...

  4. Wannafly Camp 2020 Day 6I 你吓到我的马了.jpg - BFS

    暴力BFS即可 #include <bits/stdc++.h> using namespace std; int n,m,f[105][105]; char s[105][105]; s ...

  5. 解决laravel 429请求错误

    429 Too Many Requests(过多请求) 用户在在指定的时间里发送了太多的请求.用于限制速率. 这是laravel的api访问频率 找出throttle  这个中间件,注释掉.429问题 ...

  6. 自定义输入函数 - C语言编程

    有返回功能的输入函数: #include <stdio.h> #include <conio.h> void input(char content[]); int main() ...

  7. Atom 基础使用

    当你安装好了 Atom 之后,让我们来认识一下它吧. 当你第一次打开 Atom 的时候,你会看到这样的一个窗口:   这是 Atom 的欢迎屏幕(welcome screen),它展示了一些不错的建议 ...

  8. jdk8-》stream⾥的map和filter函数使⽤

    map函数 将流中的每⼀个元素 T(入参) 映射为 R(返回值)(类似类型转换)    类似遍历集合,对集合的每个对象做处理.场景:转换对象,如javaweb开发中集合⾥⾯的DO对象转换为DTO对象 ...

  9. AcWing 275. 传纸条

    #include<iostream> using namespace std ; ; *N][N][N]; int w[N][N]; int n,m; int main() { cin&g ...

  10. linux学习笔记1:linux驱动设备概述