您的位置:首页 > 其它

带你深入了解生产消费者模型中task_done()具体作用

2020-04-01 18:35 316 查看

直奔主题

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函数
却一直阻塞没有结束。

总结

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

  1. 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函数
    在消费者消费完后才结束,而不是生产完就结束。
  2. 生产者如果被消费者的
    task_done()
    告知没有把生产者交给的任务处理完毕,那么生产者就会一直阻塞(生气…)。大家可以把sleep()函数的注释删掉看看,并且设置任意一个sleep()时间观察现象。
  3. 如果只有
    q.join()
    而没有
    task_done()
    ,消费者处理完所有任务,生产者任然阻塞,所以
    q.join()
    一般和
    q.task_done()
    配合使用。

建议自己copy代码跑跑,好好体验一下

欢迎大家评论,转载请注明出处...

  • 点赞
  • 收藏
  • 分享
  • 文章举报
傻子丶疯子 发布了10 篇原创文章 · 获赞 0 · 访问量 537 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: