Queue队列在几乎每种编程语言都会有,python的列表隐藏的一个特点就是一个后进先出(LIFO)队列。而本文所讨论的Queue是python标准库queue中的一个类。它的原理与列表相似,但是先进先出(FIFO)队列。而内部实现更为完善,有很好的数据保护机制和较高的稳定性。

Queue队列在编程中的实际应用:进程中的通信

假如两个进程需要互通数据,怎么做?用全局变量,然后在进程中通过global关键字引入全局变量?那么问题是,怎么控制时间效应问题,即什么时候获取、传送变量?如何保证数据的安全性?显然这种方案不是很恰当。python为实现进程的通信提出了几种机制,本文的Queue就是其中一种。另外还有Value,Pipe,Signal等。

关于Signal可以看看我之前写的文章:

python进程间通信--信号Signal

首先需要介绍Queue的类方法:

1. put()          将元素塞进队列,当队列满时不阻塞等待

2. put_nowait()    将元素塞进队列,当队列满时阻塞等待

3. get()           从队列中取出元素,如果队列为空,阻塞等待

4.get_nowait()     从队列中取出元素,如果队列为空,不阻塞等待

5. full()           判断队列是否为已经满

6. empty()        判断队列是否为空

7. qsize()         获取队列的元素个数

8. task_done()     当队列中的任务完成之后会自动调用task_done通知Queue,并对join()方法其作用

9. join()          阻塞等待直到所有的队列任务完成(被取出)

几个关键方法的详细解析

1. put(item,block = True,timeout = None)

将数据放进队列,item为需要塞进的元素,可以是基本数据类型变量,也可以是函数。block默认为True,即当Queue已经满时,阻塞等待(阻塞是同步的,会影响下面的程序运行)。timeout为阻塞等待超时时间,单位为秒,当超过指定时间,退出阻塞,同时报出Queue.Full错误。

2. put_nowait(item)

基本用法与put相同。当队列为满时,不阻塞等待,相当于put(item,block = False)

3. get(block= True ,timeout = None)

获取队列元素,block默认为True,当队列为空时,阻塞等待。timeout为超时时间,单位为秒,当超过指定时间,退出等待。

一、Queue类方法基本使用(为了方便调用接口,在Queue基础上再进行了一次封装):

from queue import Queue

class MyQueue():             #自定义一个MyQueue类
def __init__(self,size=3):
self.max_size = size
self.queue = Queue(size) #put()方法可以传入数值
# item1 = 2
# item2 = 3
# item3 = 3
# queue.put(item1)
# queue.put(item2)
# queue.put(item3) # 超过长度的内容
# item4 = 5
# queue.put_nowait(item4) #put()方法也可以传入函数
def _print_num(self,n):
num = n
return num def write_queue(self):
for n in range(4):
try:
self.queue.put_nowait(self._print_num(n)) #如果队列已经满了,会报出Full错误
except:
print('队列已经满了,无法添加内容') def print_queue_length(self):
print('队列的长度是:',self.queue.qsize()) def get_queue(self):
if self.queue.empty() is False:
queue_size = self.queue.qsize()
n = 1
for i in range(queue_size):
if n > queue_size:
print('队列已经空了')
value = self.queue.get()
print('队列第%s个值是:%s'%(n,value))
n += 1
else:
print('队列已经空了') #实例化代码
myqueue = MyQueue()
myqueue.write_queue()
myqueue.print_queue_length()
myqueue.get_queue()

运行结果

二、多进程间通信:

from multiprocessing import Process,Manager

#将数据装进队列
def put_msg(q,lock):
lock.acquire()
for i in range(3):
print('Put the %s into the queue'%i)
q.put(i)
lock.release() #将数据取出
def get_msg(q):
while True:
if not q.empty():
value = q.get(False)
print('Get the %s from the queue'%value)
else:
break if __name__ == '__main__':
manager = Manager()
q = manager.Queue(5) #队列长度设为5
lock = manager.Lock()
processes = []
process1 = Process(target=put_msg,args=(q,lock))
process2 = Process(target=get_msg,args=(q,)) processes.append(process1)
processes.append(process2)
for p in processes:
p.start()
p.join()

在父进程中创建Queue,传入两个子进程,因为python中父进程无法与子进程进行通信,必须使用Manage来实现。为了只有一个进程在对Queue进行操作,使用Manage的Lock。

结果:
Put the 0 into the queue
Put the 1 into the queue
Put the 2 into the queue
Get the 0 from the queue
Get the 1 from the queue
Get the 2 from the queue

解析:

操作系统中的进程本质上是一个程序在一个数据集上动态执行的过。而进程通常是由程序、数据集和进程控制块组成。

程序:也就是我们平时在IDE上编写的代码,描述了一个进程的内部运行逻辑和功能;

数据集:程序执行过程中需要使用到的资源,包括IO资源和基本数据;

进程控制块:操作系统通过进程控制块来对进程进行控制和管理,记录进程的外部特征和描述进程的执行过程

为了确保进程的独立性和安全性,操作系统在执行程序的时候会用到一种数据解构--栈。程序和数据的入栈和出栈对应进程的等待执行和正式执行。如此一来,各进程间的数据集是相互隔离的(即使可能在同一个栈中)。要进行进程间的通信或者子进程和父进程间的通信,就必须通过一定的机制。上面谈到到的Queue和Manage正是python中实现进程间通信的其中两种。

参考文章:

http://python.jobbole.com/86181/

生产者、消费者模型---Queue类的更多相关文章

  1. 生产者消费者模型(Queue,JoinableQueue)

    生产者消费者模型 主要是为解耦 借助队列来实现生产者消费者模型 栈:先进后出(First In Last Out 简称 FILO) 队列: 先进先出(First In First Out 简称 FIF ...

  2. Python学习笔记——进阶篇【第九周】———线程、进程、协程篇(队列Queue和生产者消费者模型)

    Python之路,进程.线程.协程篇 本节内容 进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Ev ...

  3. #queue队列 #生产者消费者模型

    #queue队列 #生产者消费者模型 #queue队列 #有顺序的容器 #程序解耦 #提高运行效率 #class queue.Queue(maxsize=0) #先入先出 #class queue.L ...

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

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

  5. 守护、互斥锁、IPC和生产者消费者模型

    守护进程 主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes are ...

  6. [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]

    [并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...

  7. 多线程学习-基础(十二)生产者消费者模型:wait(),sleep(),notify()实现

    一.多线程模型一:生产者消费者模型   (1)模型图:(从网上找的图,清晰明了) (2)生产者消费者模型原理说明: 这个模型核心是围绕着一个“仓库”的概念,生产者消费者都是围绕着:“仓库”来进行操作, ...

  8. python并发编程之多进程(二):互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

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

  9. python开发进程:互斥锁(同步锁)&进程其他属性&进程间通信(queue)&生产者消费者模型

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

随机推荐

  1. ajax实现异步前后台交互,模拟百度搜索框智能提示

    1.什么是异步?在传统的网站项目中,填写一堆数据,最后点击提交,在点击提交的这一刻才实现数据提交,前后台交互.在你点击提交之前数据是没有提交到后台的.这样就会造成很大的不便.比如,我填了一大堆数据,结 ...

  2. win8 notepad++ 设置无法保存

    前些天买了新笔记本.装的是win8 ,后来装了notepad++ ,最新版的,改了字体,下次从新打开之后,发现字体改动无效.后来试了一下“管理员身份运行”,再次打开,保存就有效.但总不能每次都那样去右 ...

  3. spring学习(二) ———— AOP之AspectJ框架的使用

    前面讲解了spring的特性之一,IOC(控制反转),因为有了IOC,所以我们都不需要自己new对象了,想要什么,spring就给什么.而今天要学习spring的第二个重点,AOP.一篇讲解不完,所以 ...

  4. Nacos系列:欢迎来到Nacos的世界!

    什么是Nacos? Nacos 是构建以"服务"为中心的现代应用架构 (例如微服务范式.云原生范式) 的服务基础设施. Nacos可以做什么? 1.动态配置服务:支持以中心化.外部 ...

  5. 网络爬虫之html2md

    前言 上周利用java爬取的网络文章,一直未能利用java实现html转化md,整整一周时间才得以解决. 虽然本人的博客文章数量不多,但是绝不齿于手动转换,毕竟手动转换浪费时间,把那些时间用来做些别的 ...

  6. 翻译:delete语句(已提交到MariaDB官方手册)

    本文为mariadb官方手册:DELETE语句的译文. 原文:https://mariadb.com/kb/en/delete/ 我提交到MariaDB官方手册的译文:https://mariadb. ...

  7. js_ajax模拟form表单提交_多文件上传_支持单个删除

    需求场景: 用一个input type="file"按钮上传多张图片,可多次上传,可单独删除,最后使用ajax模拟form表单提交功能提交到指定方法中: 问题:由于只有一个file ...

  8. 设置防火强开机自启,以及没有成功的tomcat开机自启

    防火墙 如果你的系统上没有安装使用命令安装 #yum install firewalld //安装firewalld 防火墙 开启服务 # systemctl start firewalld.serv ...

  9. .NET CORE 设置cookie以及获取cookie

    使用我这个方式的前提是在mvc中,确认你安装了:Microsoft.AspNetCore.Mvc. 然后在继承了Controller的类型中使用我所说的方法. 直接使用即可,我是封装了方法供我自己使用 ...

  10. 细说flush、ob_flush的区别

    ob_flush/flush在手册中的描述, 都是刷新输出缓冲区, 并且还需要配套使用, 所以会导致很多人迷惑… 其实, 他们俩的操作对象不同, 有些情况下, flush根本不做什么事情.. ob_* ...