「Python」Queue模块

转载请注明出处:https://blog.csdn.net/jinixin/article/details/80174328

 

概述

 

Queue模块,顾名思义其实现了各种队列,比如Queue,LifoQueue与PriorityQueue。

一开始我没有过多注意到该模块,随着学习深入,多线程编程越来越普遍,常常需要共享数据,而数据在共享时一旦涉及修改,就需要加锁来确保某个时刻仅有一个线程可以修改数据。

由于Queue模块是线程安全的, 故数据可以通过其来实现共享, 比起使用锁和信号量着实方便不少. 请注意该模块仅能在多线程环境中共享数据, 如果想在多进程环境中共享数据, 请使用multiprocessing.Queue模块.

 

 

构造方法

 

 

 

Queue模块中有三种顺序表,分别是Queue,LifoQueue与PriorityQueue,下面是他们对应的构造方法:

三个构造方法都有maxsize参数,表示容量。当向已满的队列中继续插入时,将引起程序阻塞或异常。当maxsize小于等于0时,表示该队列容量无上限。

 

Queue(maxsize=0)

队列,先入先出

 

LifoQueue(maxsize=0)

栈,先入后出

 

PriorityQueue(maxsize=0)

优先队列

优先队列中的元素为item,取出元素时item先按"sorted(list(item))[0])"排序,再将第一个item弹出队列。

队列中item可以是自定义类型,但别忘记在自定义类型中实现__cmp__或__lt__方法。

优先队列的例子:

#!/usr/bin/env python3
# coding=utf-8

from queue import PriorityQueue


def main():
    q = PriorityQueue(5)
    q.put([3, '满月'])
    q.put([1, '繁星'])
    q.put([4, '江上'])
    print(q.get(), q.get(), q.get())

    q = PriorityQueue(5)
    q.put(3)
    q.put(1)
    q.put(4)
    print(q.get(), q.get(), q.get())


if __name__ == '__main__':
    main()

结果:

 

常用方法

 

qsize()

返回目前队列中元素的数量

 

empty()

队列是否为空

 

full()

队列是否已满

 

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

向队列中插入item

如果队列已满,且block为True时,则在timeout秒数内阻塞,等待插入;当block为False或等待超过timeout时,抛出queue.Full异常。

如果队列已满,block为True,且timeout为None时,程序会一直阻塞直至成功插入元素。

 

put_nowait(item)

等价于put(item, block=False)

 

get(block=True, timeout=None)

从队列中取得下一个元素

如果队列为空,且block为True时,则在timeout秒数内阻塞,等待获取;当block为False或等待超过timeout时,抛出queue.Empty异常。

如果队列为空,block为True,且timeout为None时,程序会一直阻塞直至成功获取下一个元素。

 

get_nowait()

等价于get(block=False)

 

task_done()

告诉队列,之前的一次任务已完成

get()从队列中弹出并返回一个元素,该元素再被用于一系列可能的操作后,task_done()用于告诉队列这一系列操作成功执行完成。

如果在每次get()之后不调用task_done(),则之后join()方法会一直阻塞程序。

如果不使用join(),那么task_done()不需要调用。

 

join()

阻塞程序,直到队列中所有任务都完成,需和task_done()配合使用

 

 

代码


使用Queue模块的Queue队列,实现生产者与消费者:

 

 

 

#!/usr/bin/env python3
# coding=utf-8

import time
from threading import Thread
from queue import Queue, LifoQueue


def consumer(index, q):
    while True:
        if q.empty():
            break

        sleep_time = q.get(block=True, timeout=10)  # 弹出并返回
        print('%s thread sleep for %s seconds' % (index, sleep_time))
        time.sleep(sleep_time)
        q.task_done()  # 通知队列上一个get返回元素的任务已完成

    print('%s thread finished' % index)


def producer(q):
    for sleep_time in range(20):  # 将休眠时间压入队列
        q.put(sleep_time, block=True, timeout=20)


def main(q):
    thread_list = []
    for index in range(5):
        if index == 0:
            t = Thread(target=producer, args=(q,))  # 生产者
        else:
            t = Thread(target=consumer, args=(index, q))  # 消费者
        t.start()  # 开始该子线程
        thread_list.append(t)

    q.join()  # 等待队列为空,注意task_done方法必须被调用,否则一直阻塞

    for thread in thread_list:  # 等待所有子线程全部结束
        thread.join()

    print('done')


if __name__ == '__main__':
    q = Queue(5)
    # q = LifoQueue(5)
    main(q)

结果:

 


参考链接:

 

 

https://docs.python.org/3/library/queue.html

 

 

文中如有不当之处,还望包容和指出,感谢

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值