理解Queue队列中join()与task_done()的关系
在网上大多关于join()与task_done()的结束原话是这样的:
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号Queue.join() 实际上意味着等到队列为空,再执行别的操作
理解
#!/usr/bin/env python# -*- coding:utf-8 -*-'''threading test'''import threadingimport queuefrom time import sleep#之所以为什么要用线程,因为线程可以start后继续执行后面的主线程,可以put数据,如果不是线程直接在get阻塞。class Mythread(threading.Thread):def __init__(self,que):threading.Thread.__init__(self)self.queue = quedef run(self):while True:sleep(1)if self.queue.empty(): #判断放到get前面,这样可以,否则队列最后一个取完后就空了,直接break,走不到printbreakitem = self.queue.get()print(item,'!')#self.queue.task_done()returnque = queue.Queue()tasks = [Mythread(que) for x in range(1)]for x in range(10):que.put(x) #快速生产for x in tasks:t = Mythread(que) #把同一个队列传入2个线程t.start()que.join()print('---success---')

def task_done(self):'''Indicate that a formerly enqueued task is complete.Used by Queue consumer threads. For each get() used to fetch a task,a subsequent call to task_done() tells the queue that the processingon the task is complete.If a join() is currently blocking, it will resume when all itemshave been processed (meaning that a task_done() call was receivedfor every item that had been put() into the queue).Raises a ValueError if called more times than there were itemsplaced in the queue.'''with self.all_tasks_done:unfinished = self.unfinished_tasks - 1if unfinished <= 0:if unfinished < 0:raise ValueError('task_done() called too many times')self.all_tasks_done.notify_all()self.unfinished_tasks = unfinished
快速生产-快速消费
上面的演示代码是快速生产-慢速消费的场景,我们可以直接用task_done()与join()配合,来让empty()判断出队列是否已经结束。 当然,queue我们可以正确判断是否已经清空,但是线程里的get队列是不知道,如果没有东西告诉它,队列空了,因此get还会继续阻塞,那么我们就需要在get程序中加一个判断,如果empty()成立,break退出循环,否则get()还是会一直阻塞。
慢速生产-快速消费
但是如果生产者速度与消费者速度相当,或者生产速度小于消费速度,则靠task_done()来实现队列减一则不靠谱,队列会时常处于供不应求的状态,常为empty,所以用empty来判断则不靠谱。 那么这种情况会导致 join可以判断出队列结束了,但是线程里不能依靠empty()来判断线程是否可以结束。 我们可以在消费队列的每个线程最后塞入一个特定的“标记”,在消费的时候判断,如果get到了这么一个“标记”,则可以判定队列结束了,因为生产队列都结束了,也不会再新增了。 代码如下:
#!/usr/bin/env python# -*- coding:utf-8 -*-'''threading test'''import threadingimport queuefrom time import sleep#之所以为什么要用线程,因为线程可以start后继续执行后面的主线程,可以put数据,如果不是线程直接在get阻塞。class Mythread(threading.Thread):def __init__(self,que):threading.Thread.__init__(self)self.queue = quedef run(self):while True:item = self.queue.get()self.queue.task_done() #这里要放到判断前,否则取最后最后一个的时候已经为空,直接break,task_done执行不了,join()判断队列一直没结束if item == None:breakprint(item,'!')returnque = queue.Queue()tasks = [Mythread(que) for x in range(1)]#快速生产for x in tasks:t = Mythread(que) #把同一个队列传入2个线程t.start()for x in range(10):sleep(1)que.put(x)for x in tasks:que.put(None)que.join()print('---success---')
注意点:
put队列完成的时候千万不能用task_done(),否则会报错:
task_done() called too many times
因为该方法仅仅表示get成功后,执行的一个标记。
理解Queue队列中join()与task_done()的关系的更多相关文章
- 在队列中join()与task_done()的关联性
1.基础解释: Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号 Queue.join() 实际上意味着等到队列为空,再执 ...
- python threading queue模块中join setDaemon及task_done的使用方法及示例
threading: t.setDaemon(True) 将线程设置成守护线程,主进行结束后,此线程也会被强制结束.如果线程没有设置此值,则主线程执行完毕后还会等待此线程执行. t. ...
- python中的Queue(队列)详解
一.Queue简介 python中的队列分类可分为两种: 1.线程Queue,也就是普通的Queue 2.进程Queue,在多线程与多进程会介绍. Queue的种类: FIFO: Queue.Que ...
- Java 集合深入理解(9):Queue 队列
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情不太好,来学一下 List 吧! 什么是队列 队列是数据结构中比较重要的一种类型,它支持 FIFO,尾部添加.头部 ...
- python多线程中join()的理解
在 Python 的多线程编程中,经常碰到 thread.join()这样的代码.那么今天咱们用实际代码来解释一下 join 函数的作用. 第一,当一个进程启动之后,会默认产生一个主线程,因为线程是程 ...
- 【服务总线 Azure Service Bus】ServiceBus 队列中死信(DLQ - Dead Letter Queue)问题
Azure Service Bus 死信队列产生的原因 服务总线中有几个活动会导致从消息引擎本身将消息推送到 DLQ. 如 超过 MaxDeliveryCount 超过 TimeToLive 处理订阅 ...
- Python守护进程、进程互斥锁、进程间通信ICP(Queue队列)、生产者消费者模型
知识点一:守护进程 守护进程:p1.daemon=True 守护进程其实就是一个“子进程“,守护=>伴随 守护进程会伴随主进程的代码运行完毕后而死掉 进程:当父进程需要将一个任务并发出去执行,需 ...
- 进击的Python【第九章】:paramiko模块、线程与进程、各种线程锁、queue队列、生产者消费者模型
一.paramiko模块 他是什么东西? paramiko模块是用python语言写的一个模块,遵循SSH2协议,支持以加密和认证的方式,进行远程服务器的连接. 先来个实例: import param ...
- Python 源码分析:queue 队列模块
起步 queue 模块提供适用于多线程编程的先进先出(FIFO)数据结构.因为它是线程安全的,所以多个线程很轻松地使用同一个实例. 源码分析 先从初始化的函数来看: 从这初始化函数能得到哪些信息呢?首 ...
随机推荐
- Active Sync与IIS7 Classic&Integrated模式,Exchange 2007&2010的关系
上周开始一项工作,起因是因为QA同事发现我们开发的EAS hook不能在Exchange 2007 server上工作,而在Exchange 2010上可以正常工作. 环境对比如下: 1. Windo ...
- u-boot分析(十)----堆栈设置|代码拷贝|完成BL1阶段
u-boot分析(十) 上篇博文我们按照210的启动流程,分析到了初始化nand flash,由于接下来的关闭ABB比较简单所以跳过,所以我们今天按照u-boot的启动流程继续进行分析. 今天我们会用 ...
- 【MATLAB】产生FPGA中ROM需要的余弦表
产生的二进制数为带符号二进制数,最高位是符号位. function [ DATA ] = cos_gen( Num_addr,Num_out ) % 用来产生ROM需要的余弦表,输出为有符号二进制数 ...
- Java —异常
异常简介 有异于常态,和正常情况不一样,有错误出现,阻止当前方法或作用域,称为异常. Java中的异常类都继承Throwable类,它有两个子类:Error和Exception.Error很少接触,主 ...
- git 因线上分支名重复导致无法拉取代码
有时 git pull 或 git fetch 时发现 git 报了个异常,说法像是无法将线上某个分支与本地分支合并,由于分支是...(很长的hash)但是分支却是...(很长的hash) 仔细查查后 ...
- [转]Android时间获取与使用
编写Android网络程序时难免会遇到手机时间不准确的问题,本文总结了一些常用的时间获取与校正方法: 转载请注明:http://blog.csdn.net/xzy2046 1.获取本机当前时间: Ti ...
- testng失败重跑
重跑失败场景 1.要添加两个文件 背景:因为这里只是想单独展示失败的重跑的案例,所以先暂时把app这块的运行注释掉,只跑一个简单的demo,就一个简单类,类中就3个测试方法,失败重跑的原理是,运行方法 ...
- 【HDU4676】Sum Of Gcd(莫队+欧拉函数)
点此看题面 大致题意: 多组询问,求\(\sum_{i=L}^R\sum_{j=i+1}^Rgcd(i,j)\). 推式子 这道题我们可以考虑,每个因数\(d\)被统计答案的次数,肯定与其出现次数有关 ...
- Xamarin.Forms随手记
1. 更新Android SDK要从VS的工具栏上SDK Manager那里更新,不要像我一样之前搞了好几份SDK放在不同的地方,结果把自己搞糊涂了,更新了半天(真的是花了半天时间)才发现更新的地方不 ...
- ios相关配置
Deployment Target,它控制着运行应用需要的最低操作系统版本.