python-生产者消费者模型

生产者和消费者模式是多线程开发中经常见到的一种模式。生产者的线程专门用来生产一些数据,然后存放到一个中间的变量中。消费者再从这个中间的变量中取出数据进行消费。通过生产者和消费者模式,可以让代码达到高内聚低耦合的目标,程序分工更加明确,线程更加方便管理。下面分别展示Lock版本和 Condition版本的生产者和消费者模型(生产者只能生产10次)。

Lock版本的生产者和消费者模式:

import threading
import random
import timegMoney = 0
gLock = threading.Lock()
gTimes = 0class Producer(threading.Thread):def run(self) -> None:   # 箭头代表函数值返回的是Noneglobal gMoney  # 更改了全局变量需要声明global gTimeswhile True:time.sleep(1)gLock.acquire()  # 上锁if gTimes >= 10:  # 生产者只能生产10次gLock.release()  # 在退出循环之前释放锁break  # 退出循环money = random.randint(0, 100)gMoney += moneygTimes += 1print("%s生产了%d元钱"%(threading.current_thread().name,money))gLock.release()  # 释放锁class Consumer(threading.Thread):def run(self) -> None:global gMoneywhile True:time.sleep(1)gLock.acquire()money = random.randint(0,100)if gMoney >= money:  # 判断钱够不够gMoney -= moneyprint("%s消费了%d元钱"%(threading.current_thread().name,money))else:if gTimes >= 10:  # 生产者已经不再生产gLock.release()breakprint("%s想消费%d元钱,但是余额只有%d"%(threading.current_thread().name,money,gMoney))gLock.release()def main():for x in range(5):  # 创建5个生产者线程th = Producer(name="生产者%d号"%x)th.start()for x in range(5):  # 创建5个消费者线程th = Consumer(name="消费者%d号"%x)th.start()if __name__ == '__main__':main()

输出结果:

生产者0号生产了4元钱
生产者1号生产了22元钱
生产者3号生产了6元钱
消费者0号想消费72元钱,但是余额只有32
生产者4号生产了53元钱
生产者2号生产了30元钱
消费者4号消费了1元钱
消费者1号消费了39元钱
消费者3号消费了58元钱
消费者2号想消费40元钱,但是余额只有17
生产者0号生产了80元钱
消费者0号消费了71元钱
生产者3号生产了84元钱
生产者1号生产了93元钱
消费者3号消费了20元钱
消费者4号消费了92元钱
生产者2号生产了22元钱
消费者2号消费了31元钱
生产者4号生产了73元钱
消费者1号消费了41元钱
消费者0号消费了8元钱
消费者3号消费了13元钱
消费者4号消费了0元钱
消费者2号消费了72元钱
消费者0号消费了1元钱Process finished with exit code 0

Condition版本的生产者和消费者模式:

Lock版本的生产者与消费者模式可以正常的运行。但是存在一个不足,在消费者中,总是通过while True死循环并且上锁的方式去判断钱够不够。上锁是一个很耗费CPU资源的行为。因此这种方式不是最好的。还有一种更好的方式便是使用threading.Condition来实现。threading.Condition可以在没有数据的时候处于阻塞等待状态。一旦有合适的数据了,还可以使用notify相关的函数来通知其他处于等待状态的线程。这样就可以不用做一些无用的上锁和解锁的操作。可以提高程序的性能。首先对threading.Condition相关的函数做个介绍,threading.Condition类似threading.Lock,可以在修改全局数据的时候进行上锁,也可以在修改完毕后进行解锁。以下将一些常用的函数做个简单的介绍:

  1. acquire:上锁。
  2. release:解锁。
  3. wait:将当前线程处于等待状态,并且会释放锁。可以被其他线程使用notify和notify_all函数唤醒。被唤醒后会继续等待上锁,上锁后继续执行下面的代码。
  4. notify:通知某个正在等待的线程,默认是第1个等待的线程。
  5. notify_all:通知所有正在等待的线程。notify和notify_all不会释放锁。并且需要在release之前调用。

代码如下:

import threading
import random
import timegMoney = 0
gCondition = threading.Condition()
gTimes = 0class Producer(threading.Thread):def run(self) -> None:global gMoneyglobal gTimeswhile True:time.sleep(1)gCondition.acquire()if gTimes >= 10:gCondition.release()breakmoney = random.randint(0, 100)gMoney += moneygTimes += 1print("%s生产了%d元钱,剩余%d元钱"%(threading.current_thread().name,money,gMoney))gCondition.notify_all()gCondition.release()class Consumer(threading.Thread):def run(self) -> None:global gMoneywhile True:time.sleep(1)gCondition.acquire()money = random.randint(0,100)while gMoney < money:if gTimes >= 10:print("%s想消费%d元钱,但是余额只有%d元钱了,并且生产者已经不再生产了!"%(threading.current_thread().name,money,gMoney))gCondition.release()return  # 一次性将整个函数全部返回print("%s想消费%d元钱,但是余额只有%d元钱了,消费失败!"%(threading.current_thread().name,money,gMoney))gCondition.wait()gMoney -= moneyprint("%s消费了%d元钱,剩余%d元钱"%(threading.current_thread().name,money,gMoney))gCondition.release()def main():for x in range(5):th = Producer(name="生产者%d号"%x)th.start()for x in range(5):th = Consumer(name="消费者%d号"%x)th.start()if __name__ == '__main__':main()

输出结果:

生产者2号生产了18元钱,剩余18元钱
生产者3号生产了71元钱,剩余89元钱
消费者3号消费了16元钱,剩余73元钱
生产者4号生产了16元钱,剩余89元钱
生产者1号生产了52元钱,剩余141元钱
消费者4号消费了93元钱,剩余48元钱
消费者0号想消费98元钱,但是余额只有48元钱了,消费失败!
消费者1号想消费49元钱,但是余额只有48元钱了,消费失败!
消费者2号消费了18元钱,剩余30元钱
生产者0号生产了31元钱,剩余61元钱
消费者0号想消费98元钱,但是余额只有61元钱了,消费失败!
消费者1号消费了49元钱,剩余12元钱
消费者4号想消费28元钱,但是余额只有12元钱了,消费失败!
生产者2号生产了42元钱,剩余54元钱
消费者0号想消费98元钱,但是余额只有54元钱了,消费失败!
生产者4号生产了31元钱,剩余85元钱
消费者0号想消费98元钱,但是余额只有85元钱了,消费失败!
生产者1号生产了52元钱,剩余137元钱
消费者0号消费了98元钱,剩余39元钱
消费者4号消费了28元钱,剩余11元钱
消费者3号想消费76元钱,但是余额只有11元钱了,消费失败!
生产者3号生产了87元钱,剩余98元钱
生产者0号生产了59元钱,剩余157元钱
消费者3号消费了76元钱,剩余81元钱
消费者1号消费了5元钱,剩余76元钱
消费者2号消费了7元钱,剩余69元钱
消费者3号消费了55元钱,剩余14元钱
消费者4号想消费55元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者1号想消费94元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者0号想消费50元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者2号想消费52元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者3号想消费59元钱,但是余额只有14元钱了,并且生产者已经不再生产了!Process finished with exit code 0

生产者消费者模型是学习多线程的基础,我还写过一个多线程的案例——多线程下载王者荣耀高清壁纸(过程超详细)这是链接:https://blog.csdn.net/liumengqi11/article/details/112519483,核心也是生产者消费者模型,大家可以看完这篇文章后再看一下那个案例,对理解多线程有很大帮助!!
♥♥♥希望对大家有所帮助!♥♥♥

python—生产者消费者模型相关推荐

  1. Python 生产者消费者模型

    Python 生产者消费者模型 文章目录 Python 生产者消费者模型 生产者消费者模型介绍 生产者消费者模型实现 函数yield 方式 多进程方式 实现一. 实现二. 多线程方式 生产者消费者模型 ...

  2. python 生产者-消费者模型 - 代码示例

    代码示例 #!/usr/bin/env python #encoding: utf-8 import threading import timecondition = threading.Condit ...

  3. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型...

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

  4. python多线程实现生产者消费者_用Python实现多线程“生产者-消费者”模型的简单例子...

    用 Python 实现多线程"生产者 - 消费者"模型的简单例子 生产者消费者问题是一个著名的线程同步问题, 该问题描述如下: 有一个生产者在生产产品, 这些产品将提供给若干个消费 ...

  5. python生产教程_python入门教程12-09 (python语法入门之生产者消费者模型)

    Python中的生产者消费者模型,在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题,是本章的重点内容,下面我们一起来看看吧. 生产者消费者模型 在并发编程中使用生产者和消费者模式能够解决绝大 ...

  6. Python并行编程(四):多线程同步之condition(条件变量)实现带有缓冲区的生产者-消费者模型...

    什么是Condtion? 所谓condition条件变量,即这种机制是在满足了特定的条件后,线程才可以访问相关的数据. 这种同步机制就是一个线程等待特定的条件,另一个线程通知它条件已经发生.一旦条件发 ...

  7. python之生产者消费者模型

    python之生产者消费者模型 生产者消费者模型作用于: 1.爬虫的时候 2.分布式操作:celery 其本质:就是让生产数据和消费数据的效率达到平衡并且最大化的效率 为什么要使用生产者消费者模型? ...

  8. python 全栈开发,Day39(进程同步控制(锁,信号量,事件),进程间通信(队列,生产者消费者模型))...

    昨日内容回顾 python中启动子进程 并发编程 并发 :多段程序看起来是同时运行的 ftp 网盘 不支持并发 socketserver 多进程 并发 异步 两个进程 分别做不同的事情 创建新进程 j ...

  9. Python网络爬虫3 - 生产者消费者模型爬取某金融网站数据

    博客首发于www.litreily.top 应一位金融圈的朋友所托,帮忙写个爬虫,帮他爬取中国期货行业协议网站中所有金融机构的从业人员信息.网站数据的获取本身比较简单,但是为了学习一些新的爬虫方法和技 ...

最新文章

  1. Linux中yum源配置及软件安装管理
  2. 15-jQuery补充
  3. Spring 梳理 - @Component
  4. 精通init ramfs构建
  5. 【Gym - 101196F】Removal Game (环形区间dp,环状,细节优化)
  6. Clojure Project 工程文件分析
  7. javascript window.open
  8. MiniGUI编程--静态框[转]
  9. zlib库删除后的恢复
  10. python怎么更改背景颜色_python中绘图时怎么改背景颜色?
  11. vba模拟鼠标点击_手把手教罗技鼠标宏挂通行证编程
  12. win2012 安装华为U2000 U2000V200R018C60SPC200 解决”使用isql命令连接SQL Server服务失败“+
  13. python爬取网页数据总结_pycharm爬取网页数据
  14. 计算机win10装机目的,win10装机版是什么意思
  15. BlackBerry J2ME 编程指南(一)
  16. 【题解】【AcWing】1564. 哈希
  17. “碰一碰”版本的蓝牙键盘,来啦!
  18. 微服务体系中的分层设计和领域划分!
  19. 关于android系统的介绍
  20. python 安装已下载好的模块

热门文章

  1. php调用接口及编写接口
  2. 怎么把图片弄成logo_怎么把logo变成矢量图
  3. 计算机操作系统计算题及答案(5),5计算机操作系统练习题及答案.doc
  4. 骚扰电话不胜其烦 防止隐私泄露只能靠网友不满?
  5. UNIX环境高级编程(1)——UNIX系统总览
  6. 关于使用java操作doc与docx互转
  7. iOS之TabbarController和NavigationController框架
  8. cocos creator |《合成大西瓜》源码 解读
  9. 【个人小程序和企业小程序的区别】
  10. 【Unity】大世界实现方案