Python队列

Python队列:生产者消费者模式

线程安全队列(Queue)用于解决多线程开发中的数据共享与同步的问题

1.为什么使用队列

正确使用queue.Queue,可以构建出高性能的多线程程序,既充分利用多核优势,又避免复杂的锁管理问题。

多个线程同时访问共享资源时,队列通过内置锁机制提供线程安全的数据交换方式解决了以下问题

  • 线程间的安全通信
  • 数据一致性问题
  • 生产消费速率不匹配

2.队列的生命周期

生命周期:

  1. 创建队列
  2. 生产者 put 任务
  3. 消费者 get 任务
  4. 处理任务
  5. 调用task_done(确认任务完成)
  6. 队列join解除

3.队列各个阶段详解

启动阶段

  • queue.Queue()创建队列容器
  • queue.put() 添加任务到队列
# 创建线程安全队列
# maxsize限制队列长度

task_queue = queue.Queue(maxsize=100)

# 启动生产者阶段
producer_thread = threading.Thread(
        target=producer,
        args=(max_page,)
    )
    producer_thread.start()
    #等待生产完成
    producer_thread.join()

# 启动消费者阶段
consumers = []
for i in range(NUM_CONSUMERS):
    t = threading.Thread(
        target=consumer,
        args=(i + 1,)
        )
    t.start()
	consumers.append(t)
    

任务生产阶段

  • queue.get() 从队列取任务
  • None 标记任务完成
def producer(max_page):
    logger.info("生产者开始生产{}个任务",max_page)

    for page in range(max_page):
        url = f"https://example/page/{page}"
        task_queue.put(url)
    for _ in range(NUM_CONSUMERS):
        task_queue.put(None)
    logger.success("[生产者] 任务完成,已发送结束信号")

任务消费阶段

  • queue.qsize() 返回队列的大小
  • queue.task_done() 标记任务完成
def consumer(worker_id):
    while True:
        task = task_queue.get()
        try:
            if task is None:
                task_queue.task_done()
                break
            time.sleep(2)
            
            logger.success(f"[消费者{worker_id}] 请求成功|url:{task}| 队列剩余: {task_queue.qsize()}")
            task_queue.task_done()

        except Exception as e:
            logger.debug(f"{task}[消费者{worker_id}] 出现异常: {str(e)}")
            task_queue.task_done()

终止阶段

  • task_queue.join() 等待任务完成
task_queue.join()
logger.success("所有任务处理完毕")

其他方法

Queue.empty() 如果队列为空,返回True,反之False

Queue.full() 如果队列满了,返回True,反之False,Queue.full 与 maxsize 大小对应

4.完整示例代码

import queue
import time
from loguru import logger
import threading



NUM_CONSUMERS = 50

# 创建线程安全队列
task_queue = queue.Queue()

def producer(max_page):
    logger.info("生产者开始生产{}个任务",max_page)

    for page in range(max_page):
        url = f"https://example/page/{page}"
        task_queue.put(url)
    for _ in range(NUM_CONSUMERS):
        task_queue.put(None)
    logger.success("[生产者] 任务完成,已发送结束信号")


def consumer(worker_id):
    while True:
        task = task_queue.get()
        try:
            if task is None:
                task_queue.task_done()
                break
            time.sleep(2)
            logger.success(f"[消费者{worker_id}] 请求成功|url:{task}| 队列剩余: {task_queue.qsize()}")
            task_queue.task_done()

        except Exception as e:
            logger.debug(f"{task}[消费者{worker_id}] 出现异常: {str(e)}")
            task_queue.task_done()


if __name__ == '__main__':

    max_page = 5
    producer_thread = threading.Thread(
        target=producer,
        args=(max_page,)
    )
    producer_thread.start()
    producer_thread.join()

    consumers = []
    for i in range(NUM_CONSUMERS):
        t = threading.Thread(
            target=consumer,
            args=(i + 1,)
        )
        t.start()
        consumers.append(t)

    task_queue.join()
    logger.success("所有任务处理完毕")

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值