• 【Python】queue模块Queue对象


    Python中的queue模块是一个同步队列类,实现了多生产者、多消费者队列,适用于在多线程之间安全地传递消息或其他数据。Queue提供了所有必需的锁定语义。

    queue模块有三种类型的队列(只是队列中元素的提取顺序不同):先进先出(FIFO)队列,后进先出(LIFO)队列,优先级队列(涉及heapq模块)。

    其中:Queue对象 (Queue, LifoQueue, 或者 PriorityQueue) 。

    Queue:先进先出(FIFO)。LifoQueue:后进先出(LIFO)。PriorityQueue:优先级队列。

    1. from queue import Queue, LifoQueue, PriorityQueue
    2. [x for x in dir(Queue) if not x.startswith('_')]
    3. # 结果:
    4. ['empty', 'full', 'get', 'get_nowait', 'join', 'put', 'put_nowait', 'qsize', 'task_done']
    5. [x for x in dir(LifoQueue) if not x.startswith('_')]
    6. # 结果:
    7. ['empty', 'full', 'get', 'get_nowait', 'join', 'put', 'put_nowait', 'qsize', 'task_done']
    8. [x for x in dir(PriorityQueue) if not x.startswith('_')]
    9. # 结果:
    10. ['empty', 'full', 'get', 'get_nowait', 'join', 'put', 'put_nowait', 'qsize', 'task_done']

    Queue对象的方法:(以queue.Queue()为例)

    q = queue.Queue():实例化Queue对象。即线程安全队列,此队列先进先出(队尾进队头出)。可限制队列大小,超过最大限制,则会阻塞;若未提供最大限制,默认maxsize=0,则表示未限制队列大小。

    q.qsize():返回队列的大致大小(即队列中有多少元素)。多线程时,其它线程可能正在更新队列,因此只能是队列的大致大小。

    q.empty():判断队列是否为空。

    q.full():判断队列是否是满的。

    q.put(...):将元素添加到队列的队尾中。

    q.get():从队列的队头移除一个元素,并返回该元素。即从队列获取元素并从队列移除。

    q.task_done():表示之前队列中排队的任务已被执行完毕。即get()获取任务后调用task_done()则告诉队列任务已处理完。

    q.join():阻塞到队列中所有元素都被取出且被执行完毕。即队列被处理空,主线程才继续往下执行。

    举例:

    1. import threading
    2. import queue
    3. def worker():
    4. while True:
    5. # 获取元素(从队头移除元素并返回该元素)
    6. item = q.get()
    7. # 打印当前的线程名称和获取的元素
    8. print(f'Starting {threading.current_thread().name} : item = {item}\n')
    9. print(f'Finished {threading.current_thread().name} : item = {item}\n')
    10. # 告诉队列当前的任务已处理完毕
    11. q.task_done()
    12. print(f'队列是否为满:{q.full()}, 队列大致大小:{q.qsize()}。\n')
    13. # 线程安全队列,此处未限制队列大小
    14. q = queue.Queue()
    15. print(f'队列是否为空:{q.empty()}\n')
    16. # 创建4个线程,并发执行
    17. for i in range(4):
    18. t = threading.Thread(target=worker, name=f'threading{i}')
    19. t.start()
    20. # 共6个线程:当前主线程,4个创建的线程,1个socketThread
    21. print(f'共有线程{threading.active_count()}个\n {threading.enumerate()}\n')
    22. # 往队尾放入8个元素(0-7)
    23. for item in range(8):
    24. q.put(item)
    25. if item == 7: print(f'队列是否为满:{q.full()}, 队列大致大小:{q.qsize()}。\n')
    26. # 等待队列中所有元素都处理完毕,主线程继续往下执行
    27. q.join()
    28. print('All work completed')

    结果:

    补充:多生产者—多消费者【同步、互斥问题】

    固定大小的缓冲区,多个生产者往缓冲区写数据,多个消费者从缓冲区读数据。

    生产者先写数据,然后消费者才能读数据。【同步问题】

    缓冲区不满,生产者才能写数据。【同步问题】

    缓冲区互斥访问。【互斥问题】

    结合python:q = queue.Queue():线程安全队列,表示缓冲区。

                          q.put(...):生产者往缓冲区写数据。

                          q.get():消费者从缓冲区读数据。

                          Queue对象 已具备所有必需的“锁”,会为调用者处理锁定。

    参考:queue --- 一个同步的队列类 — Python 3.12.0 文档

     

  • 相关阅读:
    初识猿如意开发工具
    到底怎么个DAO
    高级数据结构——海量数据(位图,布隆过滤器)
    医院院长修电脑记
    MySQL中什么情况下会出现索引失效?如何排查索引失效?
    基于SSM实现微博系统
    优化物流运输管理,提升效率,尽在我们的小程序
    Python中的装饰器、迭代器、生成器、推导式、匿名函数和高阶函数
    Win11任务栏太宽了怎么变窄?Win11任务栏宽度调整方法
    RabbitMQ 常见问题
  • 原文地址:https://blog.csdn.net/yannan20190313/article/details/134206566