• 转载 生产消费者模型中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('生产者任务完成')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    生产: 0
    生产: 1
    生产: 2
    生产: 3
    生产: 4
    生产: 5
    消费: 0
    消费: 1
    消费: 2
    消费: 3
    消费: 4
    消费: 5
    生产: 6
    生产: 7
    生产:8
    消费: 6
    消费: 7
    消费: 8
    生产: 9
    生产任务完毕!
    消费: 9
    consumer 函数结束!
    produce 函数结束!
    消费者任务完成
    生产者任务完成
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    说明:生产任务已经完毕为什么没有直接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('生产者任务完成')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    生产: 0
    生产: 1
    生产: 2
    生产: 3
    生产: 4
    生产: 5
    生产: 6
    生产: 7
    生产: 8
    生产: 9
    消费: 0
    消费: 1
    生产任务完毕!
    produce 函数结束!
    消费: 2
    消费: 3
    消费: 4
    消费: 5
    消费: 6
    消费: 7
    消费: 8
    消费: 9
    consumer 函数结束!
    消费者任务完成
    生产者任务完成
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    说明:不带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('生产者任务完成')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    生产: 0
    生产: 1
    生产: 2
    生产: 3
    生产: 4
    生产: 5
    生产: 6
    生产: 7
    生产: 8
    生产: 9
    生产任务完毕!
    消费: 0
    消费: 1
    消费: 2
    消费: 3
    消费: 4
    消费: 5
    消费: 6
    消费: 7
    消费: 8
    消费: 9
    consumer 函数结束!
    消费者任务完成
    。。。阻塞。。。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    说明:消费者已经把任务完成了,但是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()配合使用。
    建议自己copy代码跑跑,好好体验一下
    ————————————————
    版权声明:本文为CSDN博主「qq_43577241」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/qq_43577241/article/details/104442854

  • 相关阅读:
    WinForm高级控件--PictureBox控件(图片控件)
    改变GridView中列的宽度
    RabbitMq笔记()
    参数可传可不传
    C# 视频讲解
    <ItemTemp>里写判断语句
    MyEclipse 2017 CI 10 发布(附下载)
    DevExpress v17.2新版亮点—WPF篇(四)
    DevExpress XtraScheduler日程管理控件应用实例(2)-- 深入理解数据存储
    MyEclipse移动开发教程:设置所需配置的iOS应用(三)
  • 原文地址:https://www.cnblogs.com/testzcy/p/16410794.html
Copyright © 2020-2023  润新知