关于生产消费者模型中task_done()的具体作用

 更新时间:2023年02月25日 09:41:26   作者:MicoJack Honey  
这篇文章主要介绍了关于生产消费者模型中task_done()的具体作用,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

直奔主题

tase_done()的作用:

只有消费者把队列所有的数据处理完毕,queue.join()才会停止阻塞

代码解释

#关于tase_done()的作用:只有消费者把队列所有的数据处理完毕,queue.join()才会停止阻塞
import time
from queue import Queue
from threading import Thread
q = Queue()

def produce():
    for i in range(10):
        q.put(i)
        print('生产:',i)
    print('生产任务完毕!')
    q.join()
    print(produce.__name__,'函数结束!')

def consumer():
    for i in range(10):
        print('消费:', q.get())
        q.task_done()
        # if i == 4:
        #     print('休息1s...')
        #     time.sleep(1)#sleep作用:查看生产者是否阻塞
    print(consumer.__name__,'函数结束!')



pro = Thread(target=produce)
con = Thread(target=consumer)

pro.start()
con.start()

con.join()
print('消费者任务完成')
pro.join()
print('生产者任务完成')

生产: 0
生产: 1
生产: 2
生产: 3
生产: 4
生产: 5
消费: 0
消费: 1
消费: 2
消费: 3
消费: 4
消费: 5
生产: 6
生产: 7
生产:8
消费: 6
消费: 7
消费: 8
生产: 9
生产任务完毕!
消费: 9
consumer 函数结束!
produce 函数结束!
消费者任务完成
生产者任务完成

说明:生产任务已经完毕为什么没有直接produce函数结束?

说明这里产生了阻塞,产生阻塞的原因是因为消费者没有处理完生产者所有任务。

tase_done()的作用:只有消费者把队列所有的数据处理完毕,queue.join()才会停止阻塞所以才会有produce函数结束!然后生产任务结束。

对比解释看效果

注释掉q.task_done()和q.join()

#关于tase_done()的作用:只有消费者把队列所有的数据处理完毕,queue.join()才会停止阻塞
import time
from queue import Queue
from threading import Thread
q = Queue()

def produce():
    for i in range(10):
        q.put(i)
    print('生产任务完毕!')
    # q.join()
    # if i == 4:
        #     print('休息1s...')
        #     time.sleep(1)#sleep作用:查看生产者是否阻塞
    print(produce.__name__,'函数结束!')

def consumer():
    for i in range(10):
        print('消费:', q.get())
        # q.task_done()
    print(consumer.__name__,'函数结束!')



pro = Thread(target=produce)
con = Thread(target=consumer)

pro.start()
con.start()

con.join()
print('消费者任务完成')
pro.join()
print('生产者任务完成')

生产: 0
生产: 1
生产: 2
生产: 3
生产: 4
生产: 5
生产: 6
生产: 7
生产: 8
生产: 9
消费: 0
消费: 1
生产任务完毕!
produce 函数结束!
消费: 2
消费: 3
消费: 4
消费: 5
消费: 6
消费: 7
消费: 8
消费: 9
consumer 函数结束!
消费者任务完成
生产者任务完成

说明:不带task_done()和join()情况下生产任务结束,produce函数立刻结束,并没有等待消费者处理完所有任务立即结束。

仅注释掉q.task_done()**

#关于tase_done()的作用:只有消费者把队列所有的数据处理完毕,queue.join()才会停止阻塞
import time
from queue import Queue
from threading import Thread
q = Queue()

def produce():
    for i in range(10):
        q.put(i)
    print('生产任务完毕!')
    q.join()
    print(produce.__name__,'函数结束!')

def consumer():
    for i in range(10):
        print('消费:', q.get())
        # q.task_done()
        # if i == 4:
        #     print('休息1s...')
        #     time.sleep(1)#sleep作用:查看生产者是否阻塞
    print(consumer.__name__,'函数结束!')



pro = Thread(target=produce)
con = Thread(target=consumer)

pro.start()
con.start()

con.join()
print('消费者任务完成')
pro.join()
print('生产者任务完成')

生产: 0
生产: 1
生产: 2
生产: 3
生产: 4
生产: 5
生产: 6
生产: 7
生产: 8
生产: 9
生产任务完毕!
消费: 0
消费: 1
消费: 2
消费: 3
消费: 4
消费: 5
消费: 6
消费: 7
消费: 8
消费: 9
consumer 函数结束!
消费者任务完成
。。。阻塞。。。

说明:消费者已经把任务完成了,但是produce函数却一直阻塞没有结束。

总结

通过以上分析可以得出结论:

task_done()的作用:消费者处理一个任务,它就通知生产者我处理了一个任务。

为什么要告诉生产者消费者处理了一个任务呢?

这也是为什么我进行注释对比的原因

  • 1.注释q.task_done(),不注释q.join(),我们发现produce函数一直阻塞没有结束。
  • 2.注释q.task_done(),注释q.join(),我们发现生产者生产完任务produce函数就结束了,而不是等到消费者消费完才结束。这没有task_done和join:这个模型一定是生产者先生产任务,消费者发现有任务就消费(不然会阻塞等待),所以一定是生产者生产完后就马上结束生产而消费者还没有结束。
  • 3.不注释q.task_done(),不注释q.join(),我们发现produce函数在消费者消费完后才结束,而不是生产完就结束。

生产者如果被消费者的task_done()告知没有把生产者交给的任务处理完毕,那么生产者就会一直阻塞(生气…)。

大家可以把sleep()函数的注释删掉看看,并且设置任意一个sleep()时间观察现象。

如果只有q.join()而没有task_done(),消费者处理完所有任务,生产者任然阻塞,所以q.join()一般和q.task_done()配合使用。

最后

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Python hashlib模块详细讲解使用方法

    Python hashlib模块详细讲解使用方法

    hashlib 是一个提供了一些流行的hash算法的 Python 标准库.其中所包括的算法有 md5, sha1, sha224, sha256, sha384, sha512. 另外,模块中所定义的 new(name, string=”) 方法可通过指定系统所支持的hash算法来构造相应的hash对象
    2022-11-11
  • 将Jupyter Notebook(.ipynb)文件转换为Python(.py)文件的3种方法

    将Jupyter Notebook(.ipynb)文件转换为Python(.py)文件的3种方法

    大多数数据科学在线课程都把Jupyter Notebook作为教学媒介,这是因为初学者在Jupyter Notebook的单元格中编写代码,比编写包含类和函数的脚本更容易,这篇文章主要给大家介绍了关于将Jupyter Notebook(.ipynb)文件转换为Python(.py)文件的3种方法,需要的朋友可以参考下
    2023-10-10
  • python使用Matplotlib画条形图

    python使用Matplotlib画条形图

    这篇文章主要为大家详细介绍了python使用Matplotlib画条形图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09
  • Python实现端口检测的方法

    Python实现端口检测的方法

    这篇文章主要介绍了Python实现端口检测的方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-07-07
  • Python字符串本身作为bytes进行解码的问题

    Python字符串本身作为bytes进行解码的问题

    这篇文章主要介绍了解决Python字符串本身作为bytes进行解码的问题,文末给大家补充介绍了,Python字符串如何转为bytes对象?Python字符串和bytes类型怎么互转,需要的朋友可以参考下
    2022-11-11
  • Python正则表达式如何进行字符串替换实例

    Python正则表达式如何进行字符串替换实例

    Python正则表达式在使用中会经常应用到字符串替换的代码。这篇文章主要介绍了Python正则表达式如何进行字符串替换,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2016-12-12
  • Python 图片转数组,二进制互转操作

    Python 图片转数组,二进制互转操作

    这篇文章主要介绍了Python 图片转数组,二进制互转操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-03-03
  • python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题及解决方案

    python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题

    这篇文章主要介绍了python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题,本文给大家分享解决方案,感兴趣的朋友跟随小编一起看看吧
    2020-08-08
  • 详解Python中Pytest和Unittest的区别

    详解Python中Pytest和Unittest的区别

    Pytest 和 Unittest是Python中属于最常用的两个测试框架。那么他们有些什么区别呢? Playwright 为什么只给了Pytest的深度支持,而不是Unittest呢?本文就来和大家详细聊聊
    2023-03-03
  • 在Python下尝试多线程编程

    在Python下尝试多线程编程

    这篇文章主要介绍了在Python下多线程编程的尝试,由于GIL的存在,多线程在Python开发领域一直是个热门问题,需要的朋友可以参考下
    2015-04-04

最新评论