当前位置: 首页 > news >正文

Python的`queue`模块

队列(Queue)

在Python的queue模块中,Queue类是一个线程安全的队列实现,用于在多线程编程中安全地交换信息。它遵循先入先出(FIFO)的原则。Queue类提供了几种主要的方法:

  • put(item): 将一个项目放入队列中。如果队列已满,则此方法将阻塞,直到队列中有空间可用。
  • get(): 从队列中移除并返回一个项目。如果队列为空,则此方法将阻塞,直到队列中有项目可用。
  • task_done(): 表示之前入队的一个任务已经完成。通常由使用get()的消费者线程调用。每调用一次get(),随后就应该调用一次task_done()来告诉队列该任务已处理完毕。
  • join(): 阻塞调用线程,直到队列中的所有项目都被处理并调用task_done()方法。这通常用于等待由队列消费的所有工作项完成。

并发编程中的线程

在Python中,threading模块提供了基本的线程和锁支持。每个Thread对象代表了一个线程的执行。线程之间共享全局解释器锁(GIL),这意味着在任意时刻只有一个线程可以执行Python字节码。然而,对于I/O密集型任务(如文件读写、网络请求)和等待密集型任务(如数据库查询、外部API调用),多线程仍然可以提高程序的总体性能,因为线程在等待时可以释放GIL,允许其他线程运行。

示例详解

下面是对之前示例的详细解释,包括一些注意事项和潜在的改进点:

import queue
import threading
import time
import randomdef worker(q, job_type):while True:  # 注意:这里的无限循环需要外部机制来中断if job_type == 'producer':item = random.randint(1, 100)q.put(item)print(f'{threading.current_thread().name} 生产了 {item}')time.sleep(random.random())  # 模拟耗时操作elif job_type == 'consumer':item = q.get()print(f'{threading.current_thread().name} 消费了 {item}')time.sleep(random.random())  # 模拟耗时操作q.task_done()  # 告诉队列这个任务已完成# 创建一个队列
q = queue.Queue(maxsize=10)  # 可选地设置队列的最大大小# 创建并启动生产者线程
producers = [threading.Thread(target=worker, args=(q, 'producer'), name=f'生产者-{i+1}') for i in range(2)]
for t in producers:t.daemon = Truet.start()# 创建并启动消费者线程
consumers = [threading.Thread(target=worker, args=(q, 'consumer'), name=f'消费者-{i+1}') for i in range(3)]
for t in consumers:t.daemon = Truet.start()# 注意:由于生产者线程是无限循环的,下面的q.join()将永远不会返回
# 除非有某种机制来停止生产者线程(例如,使用共享变量或threading.Event)
# 为了示例的简洁性,这里省略了停止生产者的代码# 假设我们在某个时刻决定停止所有线程
# 这可以通过设置共享变量或使用threading.Event来实现
# ...(这里省略了停止线程的代码)# 主线程通常不会在这里等待,因为它会立即继续执行后面的代码
# 但为了示例的完整性,我们在这里添加了一个简单的阻塞,以便可以看到一些输出
try:while True:time.sleep(1)
except KeyboardInterrupt:print("主线程被中断,尝试优雅地关闭所有线程...")# 在这里添加关闭所有线程的代码(如果有的话)# 注意:由于我们设置了daemon=True,主线程结束时守护线程也会自动结束# 但这通常不是优雅关闭线程的好方法

注意事项

  1. 无限循环:生产者线程中的无限循环需要外部机制来中断,否则它们将永远运行下去。
  2. 优雅关闭:在实际应用中,你需要实现一种机制来优雅地关闭线程,比如使用共享变量、threading.Eventqueue.Empty异常。
  3. GIL:虽然Python的GIL限制了多线程在CPU密集型任务上的并行性,但它对于I/O密集型任务和等待密集型任务仍然很有用。
  4. 守护线程:在这个示例中,我们使用了

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • ARM/Linux嵌入式面经(十一):地平线嵌入式实习
  • CSS实现图片裁剪居中(只截取剪裁图片中间部分,图片不变形)
  • STL——map和set
  • 微软账户和本地账户有什么区别?如何切换登录账户?
  • Unity 使用AVProMovieCapture实现Game视图屏幕录制
  • 人脸检测(Python)
  • 程序使用openmp运行后出现错乱的问题
  • JVM专题之内存模型以及如何判定对象已死问题
  • 【论文阅读】-- Strscope:不规则测量的时间序列数据的多尺度可视化
  • 开源协作wiki和文档软件Docmost
  • 生物墨水:3D组织生物打印的基石
  • 操作系统笔记分享(第一章 操作系统引论)
  • 包装类的128陷阱
  • ES6 之 Set 与 Map 数据结构要点总结(一)
  • SLF4J的介绍与使用(有logback和log4j2的具体实现案例)
  • 【面试系列】之二:关于js原型
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • 10个最佳ES6特性 ES7与ES8的特性
  • Docker: 容器互访的三种方式
  • Laravel5.4 Queues队列学习
  • node 版本过低
  • Python 基础起步 (十) 什么叫函数?
  • Webpack入门之遇到的那些坑,系列示例Demo
  • WinRAR存在严重的安全漏洞影响5亿用户
  • 多线程事务回滚
  • 批量截取pdf文件
  • 前端之React实战:创建跨平台的项目架构
  • 什么软件可以提取视频中的音频制作成手机铃声
  • 使用putty远程连接linux
  • 数组大概知多少
  • 微服务核心架构梳理
  • 微信小程序开发问题汇总
  • 原生JS动态加载JS、CSS文件及代码脚本
  • 云大使推广中的常见热门问题
  • 责任链模式的两种实现
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • 正则与JS中的正则
  • MPAndroidChart 教程:Y轴 YAxis
  • scrapy中间件源码分析及常用中间件大全
  • # 详解 JS 中的事件循环、宏/微任务、Primise对象、定时器函数,以及其在工作中的应用和注意事项
  • (2015)JS ES6 必知的十个 特性
  • (3)(3.5) 遥测无线电区域条例
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (windows2012共享文件夹和防火墙设置
  • (WSI分类)WSI分类文献小综述 2024
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (没学懂,待填坑)【动态规划】数位动态规划
  • (四)activit5.23.0修复跟踪高亮显示BUG
  • (一)80c52学习之旅-起始篇
  • (转)scrum常见工具列表
  • (转)一些感悟
  • .Net Core 微服务之Consul(二)-集群搭建
  • .NET 回调、接口回调、 委托
  • .NET/C# 使窗口永不获得焦点