python多线程(3)---生产者与消费者(线程通信)和Queue模块

Queue模块可以进行线程通信。比如生产者产生货物,货物放入队列,通过通信,消费者取得货物。Queue被称为通用队列模块
queue(size)产生一个队列,队列模式有3种,针对这三种队列分别有三个构造函数:

1 FIFO队列先进先出:class Queue.Queue(maxsize)
2 LIFO类似于堆,即先进后出:class Queue.LifoQueue(maxsize) 
3 优先级队列级别越低越先出来:class Queue.PriorityQueue(maxsize)

队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数, 默认为1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为1。如果队列为空且block为1,get()就使调用线程暂停,直至有项目可用。如果block为0,队列将引发Empty异常。join()保持阻塞状态,直到处理了队列中的所有项目为止。在将一个项目添加到该队列时,未完成的任务的总数就会增加。当使用者线程调用task_done()以表示检索了该项目、并完成了所有的工作时,那么未完成的任务的总数就会减少。当未完成的任务的总数减少到零时,join() 就会结束阻塞状态。

产生的队列实例分别有以下操作方法:

方法 描述
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
|Queue.full()| 如果队列满了,返回True,反之False |
|Queue.full()| 与 maxsize 大小对应  |

| Queue.get([block[, timeout]])| 获取队列,timeout等待时间,block不等于0.函数会阻塞到队列有对象为止|
|Queue.get_nowait()| 相当Queue.get(False) |
|Queue.put(item,block=0)| 写入队列,timeout等待时间 ,block不等于0.函数会阻塞到队列有空间为止|
| Queue.put_nowait(item)| 相当Queue.put(item, False) |
|Queue.task_done()| 在完成一项工作之后,Queue.task_done() 函数向任务已经完成的队列发送一个信号 |
|Queue.join()| 实际上意味着等到队列为空,再执行别的操作|

实例:调用前面的 MyThread.py

# -*- coding: utf8 -*-

from random import randint  # randint随机进行生产和消耗
from time import sleep
from Queue import Queue
from myThread import MyThread

#wwrite的货物对象
def writeQ(queue):
    print '放置货物', queue.put('xxx', 1)  # 把xxx对象放进队列中,并等待队列中有空间为止
    print "放置货物后当前队列大小", queue.qsize(),'\n'  # 返回队列大小

#取得货物
def readQ(queue):
    val = queue.get(1)  # 从队列中取出一个对象(消耗)
    print val+'\n'
    print '取出货物后当前队列大小', queue.qsize(),'\n'  # 返回队列大小

#writer 放置货物
def writer(queue, loops):
    """一次往队列中放进一个对象,等待一会,然后再做给定次数的相同的事"""
    for i in range(loops):
        writeQ(queue)  # 调用writeQ,放进一个对象
        sleep(randint(1, 3))  # 随机睡眠1~3秒


def reader(queue, loops):
    """一次从队列中取出一个对象,等待一会,然后做给定次数的相同的事"""
    for i in range(loops):
        readQ(queue)
        sleep(randint(2, 5))  # 睡眠时间比 write 中的长,以使 reader 在取数据的时候能够拿到数据

funcs = [writer, reader]
nfuncs = range(len(funcs))


def main():
    nloops = randint(2, 5)
    q = Queue(32)  # 创建一个大小为32的对象,和 q 绑定

    threads = []
    for i in nfuncs:
        t = MyThread(funcs[i], (q, nloops), funcs[i].__name__)  # 实例化 writer, reader 这两个对象
        threads.append(t)  # 放入空列表中

    for i in nfuncs:
        threads[i].start()  # 启动线程

    for i in nfuncs:
        threads[i].join()  # join()会等到线程结束或超时,即允许主线程等待线程结束

    print 'all DONE'

if __name__ == '__main__':  # 独立运行脚本
    main()

输出:

starting writer at: Wed Jul 20 12:18:51 2016
放置货物 starting Nonereader
 放置货物后当前队列大小at:  1Wed Jul 20 12:18:51 2016 


xxx

取出货物后当前队列大小 0 

放置货物 None
放置货物后当前队列大小 1 

xxx

取出货物后当前队列大小 0 

放置货物 None
放置货物后当前队列大小 1 

xxx

取出货物后当前队列大小 0 

放置货物 None
放置货物后当前队列大小 1 

放置货物 None
放置货物后当前队列大小 2 

xxx

取出货物后当前队列大小 1 

writer finished at: Wed Jul 20 12:19:02 2016
xxx

取出货物后当前队列大小 0 

reader finished at: Wed Jul 20 12:19:08 2016
all DONE

你可能感兴趣的:(Python)