进程Queue、线程Queue、堆栈、生产者消费者模型
没学队列之前,可以用文件实现进程之间通信
但是有2个问题:
1. 速度慢:文件是保存在硬盘空间
2. 为了数据安全要加锁(处理锁是一件很麻烦的事,容易死锁,建议自己轻易不要处理锁)
队列:队列是基于管道加锁实现的
进程Queue
进程队列:
from multiprocessing import Queue q = Queue(3)
q.put([1,2])
q.put('a')
q.put(1) print(q.get())
print(q.get())
print(q.get())
##
# [1, 2]
# a
#
取值的过程中,可能发生夯住的情况
程序卡住1:取的比放进去的多
from multiprocessing import Queue q = Queue(3)
q.put(1) print(q.get())
print(q.get()) # 放了1个,取了2次(第二次管道空了,就是取空),第2次程序卡住了(锁住了)
程序卡住2:放进去的比管道设置的多
from multiprocessing import Queue q = Queue(3)
q.put(1)
q.put(2)
q.put(2)
q.put(4) #设置管道为3,放进去4个,程序卡住了(锁住了) print(q.get())
print(q.get())
总之:取的次数不能超过放进去的次数,放进去的次数不能超过管道设置的次数
q = Queue( )
可以不设置大小,但是内存不是无限大的
不可以放大的数据(比如一个视频)(可以放一个视频连接)
线程Queue
线程队列:
import queue q = queue.Queue(3)
q.put(1)
q.put(2) print(q.get())
print(q.get()) #
#
线程--堆栈
队列:先进先出
堆栈:后进先出
import queue q = queue.LifoQueue(3)
q.put(1)
q.put(2)
q.put(3) print(q.get())
print(q.get())
print(q.get()) #
#
#
优先级队列
import queue q = queue.PriorityQueue(3)
q.put((2,'a')) #参数是一个元组,元组的第一个元素是一个数字,数字越小,优先级越高
q.put((-2,'b'))
q.put((0,'c')) print(q.get())
print(q.get())
print(q.get()) # (-2, 'b')
# (0, 'c')
# (2, 'a')
生产者和消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
如果只产生数据,不处理数据,就不需要用这个模型。
示例:
生产者和消费者中间加个队列,结耦
生产者和队列 消费者和队列
生产者产生的数据放进队列里面,消费者处理数据就从队列里面拿值
import time, os
from multiprocessing import Process, Queue def task(q):
for i in range(10):
res = '第%s个包子' % (i + 1)
time.sleep(0.2)
q.put(res)
print('%s生产了%s' % (os.getpid(),res)) def eat(q):
while True:
res = q.get()
if res is None:
break
time.sleep(0.5)
print('路人甲吃了%s' % res) if __name__ == '__main__':
q = Queue()
p1 = Process(target=task, args=(q,))
p2 = Process(target=eat, args=(q,))
p1.start()
p2.start()
p1.join()
q.put(None) #######
768生产了第1个包子
768生产了第2个包子
768生产了第3个包子
路人甲吃了第1个包子
768生产了第4个包子
768生产了第5个包子
768生产了第6个包子
路人甲吃了第2个包子
768生产了第7个包子
768生产了第8个包子
路人甲吃了第3个包子
768生产了第9个包子
768生产了第10个包子
路人甲吃了第4个包子
路人甲吃了第5个包子
路人甲吃了第6个包子
路人甲吃了第7个包子
路人甲吃了第8个包子
路人甲吃了第9个包子
路人甲吃了第10个包子
Queue是生产者给消费者发送信号
JoinableQueue 消费者给生产者发送信号
import time, os
from multiprocessing import Process, JoinableQueue def task(q):
for i in range(3):
res = '第%s个包子' % (i + 1)
time.sleep(0.2)
q.put(res)
print('%s生产了%s' % (os.getpid(), res))
q.join() #生产者生产完数据后,查看一共接收了多少个信号,如果信号数量<放进去的数据量,等待;当信号数=放进去的数据数 时,生产者执行完毕(两个数量相等,也说明了处理数据的消费者也把数据处理完了,也需要关闭了)(放在循环外面)
#生产者结束: 消费者确实把所有数据都收到 def eat(q):
while True:
res = q.get()
time.sleep(0.5)
print('%s吃了%s' % (os.getpid(), res))
q.task_done() #消费者每次拿一个值,就给生产者发送一个信号(放在循环里面,且把数据处理完之后再发送) if __name__ == '__main__':
q = JoinableQueue()
p = Process(target=task, args=(q,))
c = Process(target=eat, args=(q,))
c.daemon = True #之所以要把消费者变成守护,是因为生产者可以得到信号,自己结束,但消费者不知道什么时候结束,就会一直等待(从队列取空),变成守护后,下面的p.join()结束后,代表主进程结束,数据处理完了,消费者没必要存在了,正好主进程强制把守护关闭
p.start()
c.start()
p.join() #等待生产者结束的目的就是关闭守护(消费者没必要存在了)
进程Queue、线程Queue、堆栈、生产者消费者模型的更多相关文章
- Python守护进程、进程互斥锁、进程间通信ICP(Queue队列)、生产者消费者模型
知识点一:守护进程 守护进程:p1.daemon=True 守护进程其实就是一个“子进程“,守护=>伴随 守护进程会伴随主进程的代码运行完毕后而死掉 进程:当父进程需要将一个任务并发出去执行,需 ...
- 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)
参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...
- 线程锁、threading.local(flask源码中用的到)、线程池、生产者消费者模型
一.线程锁 线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue 线程不安全 + 人(锁) => 排队处理 1.RLock/Lock:一次放一个 a.创建10个线 ...
- 网络编程基础----并发编程 ---守护进程----同步锁 lock-----IPC机制----生产者消费者模型
1 守护进程: 主进程 创建 守护进程 辅助主进程的运行 设置进程的 daemon属性 p1.daemon=True 1 守护进程会在主进程代码执行结束后就终止: 2 守护进程内无法再开启子进程 ...
- 锁丶threading.local丶线程池丶生产者消费者模型
一丶锁 线程安全: 线程安全能够保证多个线程同时执行时程序依旧运行正确, 而且要保证对于共享的数据,可以由多个线程存取,但是同一时刻只能有一个线程进行存取. import threading v = ...
- java多线程:线程间通信——生产者消费者模型
一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...
- 基于线程实现的生产者消费者模型(Object.wait(),Object.notify()方法)
需求背景 利用线程来模拟生产者和消费者模型 系统建模 这个系统涉及到三个角色,生产者,消费者,任务队列,三个角色之间的关系非常简单,生产者和消费者拥有一个任务队列的引用,生产者负责往队列中放置对象(i ...
- 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型
一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...
- python2.0_s12_day9之day8遗留知识(queue队列&生产者消费者模型)
4.线程 1.语法 2.join 3.线程锁之Lock\Rlock\信号量 4.将线程变为守护进程 5.Event事件 * 6.queue队列 * 7.生产者消费者模型 4.6 queue队列 que ...
- 使用队列queue实现一个简单的生产者消费者模型
一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的 ...
随机推荐
- es6语法错误
哇,今天折腾了好久解决了一个问题,记录一下. 错误: 解决方法:配置babel,将es6语法转换成es5语法 1. 全局安装babel: npm install babel-cli -g 2. 本地安 ...
- Ubuntu 创建docker 容器 系列一
docker 官网安装地址:https://docs.docker.com/install/linux/docker-ce/ubuntu/ 1.Ubuntu的版本要在12.04 LTS 以上,使用un ...
- iOS UI异步更新:dispatch_async 与 dispatch_get_global_queue 的使用方法
GCD (Grand Central Dispatch) 是Apple公司开发的一种技术,它旨在优化多核环境中的并发操作并取代传统多线程的编程模式. 在Mac OS X 10.6和IOS 4.0之后开 ...
- JDBC优化策略总结
相比Hibernate.iBatis.DBUtils等,理论上JDBC的性能都超过它们.JDBC提供更底层更精细的数据访问策略,这是Hibernate等框架所不具备的. 在一些高性能的数据操作中, ...
- 第17周翻译:SQL Server中的事务日志管理的阶梯:第5级:在完全恢复模式下管理日志
来源:http://www.sqlservercentral.com/articles/Stairway+Series/73785/ 作者:Tony Davis, 2012/01/27 翻译:刘琼滨. ...
- Oracle Recycle Bin
开启回收站RECYCLEBIN=ON,默认开启 ALTER SYSTEM SET RECYCLEBIN=OFF SCOPE=SPFILE; 一.从回收站还原表 还原删除的表和从属对象. 如果多个回收站 ...
- Angular和SAP C4C的事件处理队列
Angular 我们在Angular框架的代码里能看到一个名为processQueue的函数: 这个函数是通过$scope.$apply启动的: 核心代码位于一个for循环里,循环体是一个存储异步处理 ...
- axios 里面 then 默认写的function里面没有this,改成箭头函数后就可以用this了
,methods:{ loadJson:function(){ //this.jsonTest = "jjj" this.$http.get('http://localhost:3 ...
- PHP 中空字符串介绍0、null、empty和false之间的关系
0是数字,是empty,是false,不是null,值相当于空字符串,但类型不是字符串,去空格或强制转换为字符串型时不等于空字符串 ""的值相当于0,是empty,是空字符串,是f ...
- 【转】Delphi 2010 Lite加装帮助文件
基于爱好,下载了一个delphi 2010 lite,业余玩玩. 不过这东西是网友重新打包的,没有带帮助.在网上搜索一下加摸索后搞定.步骤如下: Delphi 2010本身的帮助(MSDN风格的)1. ...