Python|队列Queue
一 前言
本文算是一次队列的学习笔记,Queue 模块实现了三种类型的队列,它们的区别仅仅是队列中元素被取回的顺序。在 FIFO 队列中,先添加的任务先取回。在 LIFO 队列中,最近被添加的元素先取回(操作类似一个堆栈)。优先级队列中,元素将保持排序( 使用 heapq 模块 ) 并且最小值的条目第一个返回。
值得注意的是 Python 2.X 版本中调用队列需要引用
import Queue而在Python 3.X版本中则需要import queue
二 队列特性
2.1 Queue的常用函数
Queue常用的方法:
qsize() 获取队列的元素个数。
put(item [,block[, timeout]]): 往queue中放一个item
get(item [,block[, timeout]]): 从queue中取出一个item,并在队列中删除的这个item
需要特别说明的是:
如果 block 为 True , timeout 为 None(也是默认的选项),那么get()/put()可能会阻塞,直到队列中出现可用的数据/位置。如果 timeout 是正整数,那么函数会阻塞直到超时N秒,然后抛出一个异常。
如果 block 为 False ,如果队列无数据,调用get()或者有无空余位置时调用put(),就立即抛出异常(timeout 将会被忽略)。
task_done(): 表示前面排队的任务已经被完成。被队列的消费者线程使用。每个 get() 被用于获取一个任务, 后续调用 task_done() 告诉队列,该任务的处理已经完成。
join(): 队列中所有的元素都被接收和处理完毕之前程序一直阻塞。
在应用程序中,如果主程序调用了join()则当前程序发生阻塞,当队列中所有的元素都被处理后,将解除阻塞(意味着每个put()进队列的条目的 task_done() 都被收到)。如果task_done()被调用的次数多于放入队列中的项目数量,将引发 ValueError 异常 。
我们通过程序向队列添加元素的时候,未完成任务的计数就会增加。每当消费者线程调用
task_done()时表示这个元素已经被回收,涉及到该元素的业务逻辑已经完成,未完成计数就会减少。当未完成计数降到零的时候,程序便会解除join()阻塞。
2.2 实践
我们用一个比较经典的案例 生产者和消费者模型,生产者生产馒头放到队列,消费者去队列里面获取馒头。
# encoding: utf-8
"""
author: yangyi@youzan.com
time: 2019/8/14 11:20 PM
func:
"""
from multiprocessing import Process, JoinableQueue, Lock
import time
import random
thread_lock = Lock()
def lock_print(msg):
with thread_lock:
print (msg)
def consumer(q):
while True:
res = q.get(block=True, timeout=3) # 如果为空 则等待3秒超时则报错退出
print('消费者拿到了 %s' % res)
q.task_done()
def producer(q):
for item in range(4):
time.sleep(random.randrange(1, 2))
q.put('馒头{0}'.format(item))
print('生产者做好了 %s' %'馒头{0}'.format(item))
q.join()
lock_print("生产结束")
if __name__ == '__main__':
print('主进程开始')
q = JoinableQueue()
pd = Process(target=producer, args=(q,))
cp = Process(target=consumer, args=(q,))
cp.daemon = True ##
pd.start()
cp.start()
pd.join()
print('主进程结束')
说明
这里生产者生产馒头并将馒头通过put()放到全局的队列中,消费者从使用get()队列中获取馒头然后调用 task_done() 通知队列中的馒头已经被消费者获取。
设置 cp.daemon = True 表示消费者进程会随主进程一起结束而结束。还有一种写法是
if __name__ == '__main__':
print('主进程开始')
q = JoinableQueue()
pd = Process(target=producer, args=(q,))
cp = Process(target=consumer, args=(q,))
pd.start()
cp.start()
pd.join()
cp.join()
print('主进程结束')
cp.join() 会让消费者进程一直等待生产者往队列放数据直到设置的超时时间。具体的逻辑需要结合自己程序的实际需求来定,是需要一直等待生产者生产数据还是随着主进程结束而结束。
三 总结
本文结合前面文章中介绍的多进程中的 守护进程和 join()方法,学习如何使用队列中的两个函数 task_done和 join。其实还有其他比较多的函数用法,需要深入的学习探索,感兴趣的朋友可以动手实践一下。
推荐阅读
https://docs.python.org/zh-cn/3/library/queue.html
https://python-parallel-programmning-cookbook.readthedocs.io/zh_CN/latest/chapter2/12_Thread_communication_using_a_queue.html
-The End-
本公众号长期关注于数据库技术以及性能优化,故障案例分析,数据库运维技术知识分享,个人成长和自我管理等主题,欢迎扫码关注。
Python|队列Queue的更多相关文章
- Python队列queue模块
Python中queue模块常用来处理队列相关问题 队列常用于生产者消费者模型,主要功能为提高效率和程序解耦 1. queue模块的基本使用和相关说明 # -*- coding:utf-8 -*- # ...
- python队列Queue
Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 基本FIFO队列 clas ...
- python socket非阻塞及python队列Queue
一. python非阻塞编程的settimeout与setblocking+select 原文:www.th7.cn/Program/Python/201406/214922.shtml 侧面认证Py ...
- python队列queue 之优先级队列
import queue as Q def PriorityQueue_int(): que = Q.PriorityQueue() que.put(10) que.put(1) que.put(5) ...
- python学习笔记——multiprocessing 多进程组件-队列Queue
1 消息队列 1.1 基本语法 消息队列:multiprocessing.Queue,Queue是对进程安全的队列,可以使用Queue实现对进程之间的数据传输:还有一个重要作用是作为缓存使用. Que ...
- Python进阶【第二篇】多线程、消息队列queue
1.Python多线程.多进程 目的提高并发 1.一个应用程序,可以有多进程和多线程 2.默认:单进程,单线程 3.单进程,多线程 IO操作,不占用CPU python的多线程:IO操作,多线程提供并 ...
- python基本数据结构栈stack和队列queue
1,栈,后进先出,多用于反转 Python里面实现栈,就是把list包装成一个类,再添加一些方法作为栈的基本操作. 栈的实现: class Stack(object): #初始化栈为空列表 def _ ...
- Python进阶(3)_进程与线程中的lock(线程中互斥锁、递归锁、信号量、Event对象、队列queue)
1.同步锁 (Lock) 当全局资源(counter)被抢占的情况,问题产生的原因就是没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果不可预期.这种现象称为“线程不安全”.在开发过 ...
- Python与数据结构[2] -> 队列/Queue[0] -> 数组队列的 Python 实现
队列 / Queue 数组队列 数组队列是队列基于数组的一种实现,其实现类似于数组栈,是一种FIFO的线性数据结构. Queue: <--| 1 | 2 | 3 | 4 | 5 |<-- ...
随机推荐
- Excel催化剂开源第34波-SM.MS图床API调用(用POST上传multipart/form-data内容)
日常做网抓数据,都是以GET请求为主,偶尔遇到需要POST请求的,一般POST的参数只是一串字符串就可以了,通过构造字符串也很容易完成,但此次SM.MS的API接口要求是Content-Type: m ...
- HelloDjango 启动!免费带你学Django全栈!
欢迎 追梦 入伙 HelloGitHub-Team,同时为我们带来了完全免费的 HelloDjango 系列教程,全网首发于 HelloGitHub 公众号.让想你的系列文章被跟多人看到,那就来加入我 ...
- C#3.0新增功能05 分部方法
连载目录 [已更新最新开发文章,点击查看详细] 分部类或结构可以包含分部方法. 类的一个部分包含方法的签名. 可以在同一部分或另一个部分中定义可选实现. 如果未提供该实现,则会在编译时删除 ...
- [leetcode] 11. Container With Most Water (medium)
原题链接 以Y坐标长度作为木桶边界,以X坐标差为桶底,找出可装多少水. 思路: 前后遍历. Runtime: 5 ms, faster than 95.28% of Java class Soluti ...
- windows下挂载linux的nfs网络硬盘
挂载命令,速度快 mount \\10.8.200.167\goworkspace z: -o nolock,rsize=1024,wsize=1024,timeo=15 安装步骤 yum insta ...
- 二、C#中数据库连接是用sqlconection 而access是用oledb对象例如:
OleDBConnection conn =new OleDBConnection();(简单记一下) 重点是研究winform 中combobox 与datagridview 的联动问题: 首先是c ...
- java多线程调用run和不调用run的区别
当在java程序中创建一个线程的时候,会三种情况: 1,只运行run方法 2,先执行start,再执行run方法 3,只运行start方法 三者的区别如下: 运行方式 区别 只运行run 只运行run ...
- java的System.currentTimeMillis()和System.nanoTime
纳秒 ns(nanosecond):纳秒, 时间单位.一秒的10亿分之一,即等于10的负9次方秒.常用作 内存读写速度的单位,其前面数字越小则表示速度越快. 1纳秒=1000 皮秒 1纳秒 = ...
- Mysql 学校信息管理系统
1.创建数据库语句: #创建数据库 CREATE DATABASE `schoolDB`; USE `schoolDB`; #创建学生表 CREATE TABLE `student`( `sid` I ...
- 12. 集合类Collection和Map
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...