进程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实现一个简单的生产者消费者模型
一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的 ...
随机推荐
- 在自己的工程中使用ijkplayer的功能
最近在做一个软解视频叠加硬解视频的方案,网上看了很多教程,始终不得要领.虽然ijkplayer提供了ijkplayer-example这个示例工程,但对于初入安卓的人来说,要将ijkplayer整合到 ...
- oracle适配器连接不上解决方案
Oracle适配器连接不上解决方案 作者:Vashon oracle 的Developer连接不上报错:listener does not currently know of SID given in ...
- 无法登录phpmyadmin,报1130错误
分析过程及解决方案: mysql的1130错误是远程连接的用户无远程权限问题导致.解决方案:在本机登入mysql后,更改 “mysql” 数据库里的 “user” 表里的 “host” 项,从”loc ...
- Makeflie自动生成依赖,自动化编译
在netbeans里开发,有一个重要文件makefile,是用来编译所有的文件. 项目的目录结构如下,扁平的目录结构,如何实现自动化编译,写makefile呢? 第一版 基础版: CC = g++ C ...
- Eclipse添加默认的JRE
打开eclipse,依次点击如下选项Window->Preferences-> Java -> Installed JREs.步骤见下图. 选中Installed JREs选项出 ...
- 大数据开发学习之构建Hadoop集群-(0)
有多种方式来获取hadoop集群,包括从其他人获取或是自行搭建专属集群,抑或是从Cloudera Manager 或apach ambari等管理工具来构建hadoop集群等,但是由自己搭建则可以了解 ...
- JQQ文字素材
1.十二生肖:子鼠.丑牛.寅虎.卯兔.辰龙.巳舍.午马.未羊.申猴.酉鸡.戌狗.亥猪.丙申年(2016)乙未年(2015)甲午年(2014)癸巳年(2013)壬辰年(2012)辛卯年(2011)庚寅年 ...
- DELETE - 删除一个表中的行
SYNOPSIS DELETE FROM [ ONLY ] table [ WHERE condition ] DESCRIPTION 描述 DELETE 从指明的表里删除满足 WHERE 子句的行. ...
- mysql利用binlog恢复数据
需求:需要给开发提供一个2018年9月30号的数据,按照我们公司正常备份策略来说,直接找到对应时间的备份数据,解压导入即可,恰好这个时间节点的数据没有,只备份到2018年9月25号的,糟糕了吧 咋办呢 ...
- python3查询Excel中A表在B表没有的数据,并保存到新的Excel,这里用的是“xlrd”和“xlwt”
import xlrd import xlwt # 打开A表,将A表的数据存放到cols1中,这里打印出来是方便查看测试数据. data1 = xlrd.open_workbook(r'F:\cars ...