生产者、消费者模型---Queue类
2018-11-26 08:01:05来源:博客园 阅读 ()
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/
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- python 之 并发编程(生产者消费者模型、守护进程的应用) 2019-07-24
- 文本分类问题相关原理知识 2019-07-24
- python学习-40 生产者和消费者模型 2019-07-24
- python 之网络并发(非阻塞IO模型) 2019-07-24
- Web框架之Django_06 模型层了解(F查询、Q查询、事务、updat 2019-06-14
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash