没学队列之前,可以用文件实现进程之间通信

但是有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、堆栈、生产者消费者模型的更多相关文章

  1. Python守护进程、进程互斥锁、进程间通信ICP(Queue队列)、生产者消费者模型

    知识点一:守护进程 守护进程:p1.daemon=True 守护进程其实就是一个“子进程“,守护=>伴随 守护进程会伴随主进程的代码运行完毕后而死掉 进程:当父进程需要将一个任务并发出去执行,需 ...

  2. 进程同步控制(锁,信号量,事件), 进程通讯(队列和管道,生产者消费者模型) 数据共享(进程池和mutiprocess.Pool模块)

    参考博客 https://www.cnblogs.com/xiao987334176/p/9025072.html#autoid-1-1-0 进程同步(multiprocess.Lock.Semaph ...

  3. 线程锁、threading.local(flask源码中用的到)、线程池、生产者消费者模型

    一.线程锁 线程安全,多线程操作时,内部会让所有线程排队处理.如:list/dict/Queue 线程不安全 + 人(锁) => 排队处理 1.RLock/Lock:一次放一个 a.创建10个线 ...

  4. 网络编程基础----并发编程 ---守护进程----同步锁 lock-----IPC机制----生产者消费者模型

    1  守护进程: 主进程 创建 守护进程   辅助主进程的运行 设置进程的 daemon属性 p1.daemon=True 1 守护进程会在主进程代码执行结束后就终止: 2 守护进程内无法再开启子进程 ...

  5. 锁丶threading.local丶线程池丶生产者消费者模型

    一丶锁 线程安全: 线程安全能够保证多个线程同时执行时程序依旧运行正确, 而且要保证对于共享的数据,可以由多个线程存取,但是同一时刻只能有一个线程进行存取. import threading v = ...

  6. java多线程:线程间通信——生产者消费者模型

    一.背景 && 定义 多线程环境下,只要有并发问题,就要保证数据的安全性,一般指的是通过 synchronized 来进行同步. 另一个问题是,多个线程之间如何协作呢? 我们看一个仓库 ...

  7. 基于线程实现的生产者消费者模型(Object.wait(),Object.notify()方法)

    需求背景 利用线程来模拟生产者和消费者模型 系统建模 这个系统涉及到三个角色,生产者,消费者,任务队列,三个角色之间的关系非常简单,生产者和消费者拥有一个任务队列的引用,生产者负责往队列中放置对象(i ...

  8. 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型

    一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...

  9. python2.0_s12_day9之day8遗留知识(queue队列&生产者消费者模型)

    4.线程 1.语法 2.join 3.线程锁之Lock\Rlock\信号量 4.将线程变为守护进程 5.Event事件 * 6.queue队列 * 7.生产者消费者模型 4.6 queue队列 que ...

  10. 使用队列queue实现一个简单的生产者消费者模型

    一.生产者消费者模型 我们去超市商店等地购买商品时,我们大部分人都会说自己是消费者,而超市的各大供货商.工厂等,自然而然地也就成了我们的生产者.如此一来,生产者有了,消费者也有了,那么将二者联系起来的 ...

随机推荐

  1. ArcGIS Desktop新建postgresql版sde(10.4.1)的连接

    假设连接到的sde数据库是pg数据库,其他参数包括: ip:10.0.0.8 数据库:sde1 用户:sde 密码:sde 打开catalog,新建数据库连接 按如下输入数据库连接参数 红框1是数据库 ...

  2. Kotlin学习的一些心得

    1.工程manifest中的application节点有冲突时,添加 xmlns:tools="http://schemas.android.com/tools" tools:re ...

  3. Android Learning Note -- AsyncTask浅尝

    AsyncTask 实现原理 AsyncTask是Android提供的轻量级异步类,可以直接继承AsyncTask在类中实现异步操作,并提供接口反馈当前的异步执行程度(通过接口实现UI进度更新),最后 ...

  4. jsp <%@ include %> 例子

    <%@ include %>:所有代码包含进来之后一起进行处理,最终编译成一个servlet. jsp文件中添加top和bottom.jsp页面 empList.jsp <%@ pa ...

  5. 更新centos系统的python版本

    因今天安装一程序需要用到python高版本,所以升级来系统自带的python. 先查询下系统的python版本是多少. #python -V 显示出来的是2.4.3,太老了,现在升级到比较稳定的版本3 ...

  6. 算法之A星算法(寻路)

    1.启发式搜索:启发式搜索就是在状态空间中的搜索对每一个搜索的位置进行评估,得到最好的位置,再从这个位置进行搜索直到目标.这样可以省略大量无谓的搜索路径,提高了效率.在启发式搜索中,对位置的估价是十分 ...

  7. 管道命令和xargs的区别(经典解释) 自己的总结

    1. 简介 之所以能用到这个命令,关键是由于很多命令不支 持|管道来传递参数,而日常工作中有有这个必要, 所以就有了xargs命令,例如:find /sbin -perm +700 |ls -l 这个 ...

  8. drawer 抽屉 弹框 在 modal的后面的解决方案

    drawer 抽屉 弹框 在 modal的后面的解决方案 方案1 在框内 弹出 <Drawer title="拍照" :transfer="false" ...

  9. 用Vue的方式实现复选框

    var borrVm = new Vue({ el: "#WingApp", data: { returnBookList:[], checked:"", ch ...

  10. python导包一不小心就入坑(常用解决办法)

    常见导包报错: - ImportError:No module named - SystemError: Parent module '' not loaded, cannot perform rel ...