Python 之队列(queue)的创建、数据进出及线程间使用

2024-05-02 13:08

本文主要是介绍Python 之队列(queue)的创建、数据进出及线程间使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

____tz_zs

队列(queue),是线程间最常用的交换数据的形式,用来在生产者和消费者线程之间的信息传递,是适用于多线程编程的先进先出的数据结构。

一、创建队列对象

1、FIFO 队列(first-in,first-out 先进先出)

class queue.Queue(maxsize=0)
maxsize:(可选参数,默认为 0)用于设定队列长度。maxsize 小于等于 0 则表示队列长度无限。 一旦队列长度达到其设定上限,插入会导致阻塞,直到队列中的数据被消费掉。

2、LIFO 队列(last-in,first-out 后进先出)

class queue.LifoQueue(maxsize=0)
maxsize:(可选参数,默认为 0)用于设定队列长度。maxsize 小于等于 0 则表示队列长度无限。 一旦队列长度达到其设定上限,插入会导致阻塞,直到队列中的数据被消费掉。

3、优先级队列

class queue.PriorityQueue(maxsize=0)

二、往队列中添加项目(Queue.put)

将一个 item 放入队列。

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

参数:
tiem:将要放入队列中的对象。
block:可选,说明是否阻塞。
timeout:可选,指定等待时间。

  • 如果可选参数 block 为 true 并且 timeout 为None(即默认值),则在队列没有空闲空间时阻塞,永远等待下去,直到有空闲空间时放入数据。
  • 如果可选参数 block 为 true 并且 timeout 是正数,则在队列没有空闲空间时阻塞,它最多会阻塞 timeout 秒,如果超出了这个时间仍然没有空闲空间,则会抛出 queue.Full 异常。
  • 如果可选参数 block 为 true ,则在队列有空闲空间时立即将数据放入队列中,如果没有空闲空间则立刻抛出 queue.Full 异常(在这种情况下忽略参数 timeout)。

ps:
Queue.put_nowait(item) 等同于 put(item, False)

三、从队列中取出数据(Queue.get)

从队列中移除并返回一个 item。

Queue.get(block=True, timeout=None)

参数:
block:可选,说明是否阻塞。
timeout:可选,指定等待时间。

  • 如果可选参数 block 为 true 并且 timeout 为None(即默认值),则在队列中没有数据时阻塞,永远等待下去,直到队列中有数据可以获取。
  • 如果可选参数 block 为 true 并且 timeout 是正数,则在队列中没有数据时阻塞,它最多会阻塞 timeout 秒,如果超出了这个时间而队列中仍然没有数据,则会抛出 queue.Empty 异常。
  • 如果可选参数 block 为 true ,则在队列有数据时立即取出,如果没有数据则立刻抛出 queue.Empty 异常(在这种情况下忽略参数 timeout)。

ps:
Queue.get_nowait() 相当于 get(False) 。

四、Queue.join() 和 Queue.task_done() 的使用

  • 每当有 item 被 put 到队列时,未完成任务的计数(Queue 对象 的 unfinished_tasks 属性)就会加 1。
  • 每当调用 task_done()方法时,计数就会减 1。当未完成任务的数量降至 0 时,Queue.join()的阻塞消失。

例1:队列中存储了三个 item,在线程结束时队列随之消失。

# -*- coding:utf-8 -*-
"""
@author: tz_zs
"""import queueq = queue.Queue()
print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数q.put(222)
q.put(333)
q.put(444)print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数print("结束")"""
队列大小:0
未完成的任务数:0
队列大小:3
未完成的任务数:3
结束Process finished with exit code 0
"""

例2:队列中存入三个 item,未完成任务的计数为3,未处理完,所以进程阻塞在 Queue.join() 处。

# -*- coding:utf-8 -*-
"""
@author: tz_zs
"""import queueq = queue.Queue()
print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数q.put(222)
q.put(333)
q.put(444)print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数q.join()
print("结束")"""
队列大小:0
未完成的任务数:0
队列大小:3
未完成的任务数:3
"""

例3:队列中存入三个 item,未完成任务的计数为3。虽然已通过 Queue.get() 取出,但计数并没有减少,进程仍阻塞在 Queue.join() 处。

# -*- coding:utf-8 -*-
# -*- coding:utf-8 -*-
"""
@author: tz_zs
"""import queueq = queue.Queue()
print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数q.put(222)
q.put(333)
q.put(444)
q.get()
q.get()
q.get()print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数q.join()
print("结束")"""
队列大小:0
未完成的任务数:0
队列大小:0
未完成的任务数:3
"""

例4:队列中存入三个 item,未完成任务的计数为3。通过调用 Queue.task_done() 将计数减少到 0,线程未阻塞。

# -*- coding:utf-8 -*-
"""
@author: tz_zs
"""import queueq = queue.Queue()
print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数q.put(222)
q.put(333)
q.put(444)
q.task_done()
q.task_done()
q.task_done()print("队列大小:%s" % q.qsize())  # 队列大小
print("未完成的任务数:%s" % q.unfinished_tasks)  # 未完成的任务数q.join()
print("结束")"""
队列大小:0
未完成的任务数:0
队列大小:3
未完成的任务数:0
结束Process finished with exit code 0
"""

五、队列大小的相关属性和方法

1、Queue.qsize()

返回队列的大致大小。注意,qsize() > 0 不保证后续的 get() 方法不被阻塞,qsize() < maxsize 也不保证 put() 方法不被阻塞。

2、Queue.empty()

如果队列为空,返回 True ,否则返回 False 。如果 empty() 返回 True ,不保证后续调用的 put() 不被阻塞。类似的,如果 empty() 返回 False ,也不保证后续调用的 get() 不被阻塞。

3、Queue.full()

如果队列是满的返回 True ,否则返回 False 。如果 full() 返回 True 不保证后续调用的 get() 不被阻塞。类似的,如果 full() 返回 False 也不保证后续调用的 put() 不被阻塞。

4、Queue.maxsize

属性,创建队列时传入参数,代表队列的最大容量,小于等于 0 代表无线。

5、Queue.queue

# -*- coding:utf-8 -*-
"""
@author: tz_zs
"""import queueq = queue.Queue()q.put(222)
q.put(333)
q.put(444)
dq = q.queue  # deque([222, 333, 444])
print(dq)
l = list(dq)  # <class 'list'>: [222, 333, 444]
print(l)
"""
deque([222, 333, 444])
[222, 333, 444]
"""

六、官网例子:如何等待排队的任务被完成的示例

def worker():while True:item = q.get()if item is None:breakdo_work(item)q.task_done()q = queue.Queue()
threads = []
for i in range(num_worker_threads):t = threading.Thread(target=worker)t.start()threads.append(t)for item in source():q.put(item)# block until all tasks are done
q.join()# stop workers
for i in range(num_worker_threads):q.put(None)
for t in threads:t.join()

这篇关于Python 之队列(queue)的创建、数据进出及线程间使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/954316

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

JDK21对虚拟线程的几种用法实践指南

《JDK21对虚拟线程的几种用法实践指南》虚拟线程是Java中的一种轻量级线程,由JVM管理,特别适合于I/O密集型任务,:本文主要介绍JDK21对虚拟线程的几种用法,文中通过代码介绍的非常详细,... 目录一、参考官方文档二、什么是虚拟线程三、几种用法1、Thread.ofVirtual().start(

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

Python版本信息获取方法详解与实战

《Python版本信息获取方法详解与实战》在Python开发中,获取Python版本号是调试、兼容性检查和版本控制的重要基础操作,本文详细介绍了如何使用sys和platform模块获取Python的主... 目录1. python版本号获取基础2. 使用sys模块获取版本信息2.1 sys模块概述2.1.1

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D