进程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实现一个简单的生产者消费者模型
一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的 ...
随机推荐
- mac及windows下安装ss实现***
官网下载shadowsock(mac/windows都是下面地址,页面会根据当前系统自动判断所下载的包) https://sourceforge.net/projects/shadowsocksgui ...
- Java Web 开发中路径相关问题小结
Java Web开发中路径问题小结 (1) Web开发中路径的几个基本概念 假设在浏览器中访问了如下的页面,如图1所示: 图1 Eclipse中目录结构如图2所示: 图2 那么针对这个站点的几个基本概 ...
- git设置log的别名 for hist
hist -- alias for 'log --color --graph --date=short --pretty=format:'%Cred%h%Creset -%C(yellow)%d%C ...
- 46 Simple Python Exercises-Higher order functions and list comprehensions
26. Using the higher order function reduce(), write a function max_in_list() that takes a list of nu ...
- vijos 1053 Easy sssp
描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一 ...
- EOS Dawn 3.0 智能合约 -- 新格式
1.简介 随着EOS Dawn 3.0发布,智能合约的坑又要重新踩了o(╥﹏╥)o:3.0不仅将原来本身就在链里的基础合约独立出来,简单的介绍见3.0合约改变,合约的书写方式也有巨大变化,相比之前更加 ...
- css3 calc()属性介绍以及自适应布局使用方法
前端知识 Calc()介绍 calc的英文是calculate的缩写,中文为计算的意思,是css3的一个新增的功能,用来只当元素的长度.比如说:你可以用calc()给元素margin.padding. ...
- Linux一些常用小命令
使用xshell连接虚拟机 rz 上传的linux服务器 sz 从服务器上下载 df 查看磁盘大小 -h du 查看所有磁盘(硬盘)大小(-h 可读 -s统计当前目录的大小)du -sh free ...
- this.$Message.success('提示信息') 少写了一个c 导致报错
this.$Message.success('提示信息') 少写了一个c 导致报错 而且 $Message 输出还没显示,导致我以为是没有 $Message 对象了,其实全局对象直接调用即可
- CWnd::Updata的作用
CWnd::Updata的作用 CWnd::UpdateData 调用此成员函数以在对话框中初始化数据,或者取回和验证对话框数据. BOOL UpdateData(BOOL bSaveAndValid ...