5.Python的Queue模块

来源:互联网 发布:java线程 pdf 编辑:程序博客网 时间:2024/05/14 13:27

载*请注明原始出处: http://blog.csdn.net/a464057216/article/details/48103125

Queue模块提供了对“多生产者,多消费者”队列模型的支持,是线程安全的模块,在多线程之间传递数据时尤其有用。如果只是想使用队列这种数据结构,可以参考collections.deque模块。
Queue模块内包含三种队列:

  • class Queue.Queue(maxsize = 0):FIFO队列,maxsize指定了队列的大小,如果队列已满,将不能插入新的元素,除非队列中有元素被消耗。如果maxsize为零或者负数,则队列的大小是无限大。
  • class Queue.LifoQueue(maxsize = 0):LIFO队列,maxsize的含义与Queue.Queue中一致。
  • class Queue.PriorityQueue(maxsize = 0):优先级队列(内部其实由heapq模块实现),maxsize的含义与Queue.Queue中一致。优先级最小的项目被优先取出,优先级的排序其实是根据sorted(list(entries)[0])的结果,每个项目的格式是(priority_number, data)的元组。

Queue模块还有两种异常,是上面三种队列公用的:

  • exception Queue.Empty:当一个Queue对象中无元素,却对这个Queue对象调用了非阻塞的get()或者get_nowait()方法的时候抛出。
  • exception Queue.Full:当一个Queue对象中元素已满,却对这个Queue对象调用了非阻塞的put()或者put_nowait()方法的时候抛出。

Queue模块还提供了如下几种操作队列的方法,都是上面三种队列公用的:

  • Queue.qsize():返回队列的近似大小。如果qsize()的返回值大于零,不代表接下来的get()操作不会被阻塞,同样,如果qsize()的返回值小于maxsize,也不代表接下来的put()操作不会被阻塞。
  • Queue.empty():如果队列为空,返回True,否则返回False。如果empty()的返回值是True,不代表接下来的put()操作不会被阻塞,同样,如果empty()的返回值是False,不代表接下来的get()操作不会被阻塞。
  • Queue.full():如果队列满,返回True,否则返回False。如果full()的返回值是True,不代表接下来的get()操作不会被阻塞,同样,如果full()的返回值是False,不代表接下来的put()操作不会被阻塞。
  • Queue.put(item, block = True, timeout = None):向队列中添加元素。如果block = True,则当队列已满时,会一直阻塞(只能阻塞执行线程本身,不能阻塞其他线程)到队列中有空余位置时再添加元素。如果block = True时,设置了timeout,则会一直阻塞timeout时间,到时有空余位置就添加元素,没有空余位置就抛出Queue.Full异常。如果block = False,则忽略timeout参数,是非阻塞插入,如果有空余位置就添加元素,如果没有空余位置就直接抛出Queue.Full异常。
  • Queue.put_nowait(item):相当于put(item, block = False)。
  • Queue.get(block = True, timeout = None):从队列中取出一个元素。如果block = True,则当队列中无元素时,会一直阻塞等到队列中有一个元素时再取出。如果block = True时,设置了timeout,则会一直等待timeout时间,到时如果队列中有元素就取出,如果没有就抛出Queue.Empty异常。如果block = False,则忽略timeout参数,是非阻塞取出,如果有元素就取出,没有元素直接抛出Queue.Empty异常。
  • Queue.get_nowait():相当与get(block = False)。

先举一个单线程使用Queue.Queue的例子:

import Queuequeue = Queue.Queue(3)queue.put(6)print 'After put 6, queue size:', queue.qsize()print 'Put 2.'queue.put(2)print 'Is queue full?:', queue.full()print 'Is queue empty?:', queue.empty()print 'Put 4.'queue.put(4)print 'Is queue full?:', queue.full()item = queue.get()print 'Item getted:', item

执行结果如下:

After put 6, queue size: 1Put 2.Is queue full?: FalseIs queue empty?: FalsePut 4.Is queue full?: TrueItem getted: 6

后进先出队列与Queue.Queue类似,在此不再举例,下面是一个优先级队列的例子:

import Queuequeue = Queue.PriorityQueue(3)queue.put((2,'Two'))queue.put((1,'One'))queue.put((6,'Six'))item = queue.get()print 'Item getted:', item

执行结果如下:

mars@mars-Ideapad-V460:~/test$ python test2.pyItem getted: (1, 'One')

针对“多生产者,多消费者”模型,Queue模块还提供了如下两个方法跟踪入队列的元素的处理情况:
- Queue.task_done():通常由消费者线程调用,表示之前get()到的元素已经处理完毕,通知给Queue。如果task_done()的调用次数比队列中的元素多,会抛出ValueError异常。
- Queue.join():阻塞线程,直到队列中的所有元素被处理完毕。向队列中添加元素会使未处理元素个数加1,从队列中取出元素会使未处理元素个数减1,如果未处理元素个数降至0,join解除阻塞。
下面先举一个简单的多线程例子:

#!/usr/bin/env python# -*- coding: utf-8 -*-# @author: Mars Looimport threadingimport Queueimport timeclass Producer(threading.Thread):    def __init__(self, q):        self.q = q        super(Producer, self).__init__()    def run(self):        time.sleep(1)        self.q.put(3)class Consumer(threading.Thread):    def __init__(self, q):        self.q = q        super(Consumer, self).__init__()    def run(self):        while True:            try:                print 'Start to get'                item = self.q.get_nowait()                print 'Got the item:', item                print 'Got time:', time.ctime()                break            except Exception, exc:                print excst = time.ctime()q = Queue.Queue(3)c = Consumer(q)p = Producer(q)p.start()c.start()c.join()print 'Task begin time:', st 

执行结果如下:

Start to get(还有很多Start to get的显示,奇怪的是异常抓不到)Start to getStart to getStart to getStart to getStart to getStart to getGot the item: 3Got time: Sun Aug 30 20:44:55 2015Task begin time: Sun Aug 30 20:44:54 2015

如果采用get的阻塞版本:

def run(self):        while True:            try:                print 'Start to get'                item = self.q.get()                print 'Got the item:', item                print 'Got time:', time.ctime()                break            except Exception, exc:                print exc

执行结果变成这样:

mars@mars-Ideapad-V460:~/test$ python test.pyStart to getGot the item: 3Got time: Sun Aug 30 20:46:21 2015Task begin time: Sun Aug 30 20:46:20 2015

下面举一个使用task_done和join的例子:

#!/usr/bin/env python# -*- coding: utf-8 -*-# @author: Mars Looimport threadingimport Queueimport time, randomdef worker(q):    while True:        item = q.get()        print 'Working on', item        time.sleep(random.randint(1,100)/100.0)        q.task_done()q = Queue.Queue()for i in range(15):    t = threading.Thread(target = worker, args = (q,))    t.setDaemon(True)    t.start()for item in range(50,60):    q.put(item)q.join()print 'All done!'

执行结果如下:

mars@mars-Ideapad-V460:~/test$ python test.pyWorking on Working on Working on5150 52Working on Working onWorking on 53 5554 Working on 56Working onWorking on 58Working on 59 57All done!

如果觉得我的文章对您有帮助,欢迎关注我(CSDN:Mars Loo的博客)或者为这篇文章点赞,谢谢!

1 0
原创粉丝点击