生产者和消费者模型,为什么代码正常运行,却无法结束?

生产者和消费者模型,为什么代码正常运行,却无法结束?

import threading
import time
import queue
import random

# 创建队列
q = queue.Queue()


# 生产者
def Producer(name):
    for i in range(10):
        # 将制作的小蛋糕放入队列中
        # 生产者按照生产蛋糕的顺序来给蛋糕做标志
        cake = {}
        cake[name] = i+1
        q.put(cake[name])
        # print('%s制作了%s个蛋糕' % (name, cake[name]))
        time.sleep(1)
        

# 消耗者
def Consumer(name):
    while True:
        # 取出蛋糕并吃掉
        get_cake = q.get()
        eat_cake = []
        eat_cake.append(get_cake)
        cake_num = len(eat_cake)
        # print(get_cake)
        print(f'{name}吃掉1个蛋糕,还剩{10-get_cake}个')
        time.sleep(0.3)              
    return '%s共吃掉%s个蛋糕' % (name, cakes_num)

if __name__ == '__main__':
    # 创建线程,一个生产者,三个消费者
    p = threading.Thread(target=Producer, args=('慕慕',))
    c1 = threading.Thread(target=Consumer, args=('小明',))
    c2 = threading.Thread(target=Consumer, args=('小红',))
    c3 = threading.Thread(target=Consumer, args=('安安',))
    p.start()
    
    c1.start()
    c2.start()
    c3.start()
        
    p.join()
    c1.join()
    c2.join()
    c3.join()

return 语句为什么无法返回呢?
图片描述

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

同学,你好!1

1、因为while True 一直为真,所以一直在循环while语句,所以执行不到后续的 return  语句,同学可以在while 循环中加个判断,如果队列为空则停止循环,代码如下图:

https://img1.sycdn.imooc.com//climg/6352029709f9c4a205900135.jpg

while 循环结束后可以执行到return 语句,但是return 是函数返回值,需要函数调用处进行输出,线程无法实现。不能实现统计每人吃了多少蛋糕。可以定义一个字典,对人名进行判断,对人名出现次数进行累加,就是一个人吃了多少块蛋糕。具体代码如下图:

import threading
import time
import queue
import random

# 创建队列
q = queue.Queue()
# 生产者
def Producer(name):
    for i in range(10):
        # 将制作的小蛋糕放入队列中
        # 生产者按照生产蛋糕的顺序来给蛋糕做标志
        cake = {}
        cake[name] = i + 1
        q.put(cake[name])
        print('%s制作了%s个蛋糕' % (name, cake[name]))
        time.sleep(1)

user={"小红":0,"安安":0,"小明":0}
# 消耗者
def Consumer(name):
    while True:
        # 取出蛋糕并吃掉
        get_cake = q.get()
        eat_cake = []
        eat_cake.append(get_cake)
        cake_num = len(eat_cake)
        if name=="小明":
           user["小明"] +=1
        elif name == "安安":
           user["安安"] += 1
        else:
           user["小红"] += 1
        print(f'{name}吃掉1个蛋糕,还剩{10 - get_cake}个')
        time.sleep(3)
        if q.empty():
            break
    # return '%s共吃掉%s个蛋糕' % (name, cakes_num)


if __name__ == '__main__':
    # 创建线程,一个生产者,三个消费者
    p = threading.Thread(target=Producer, args=('慕慕',))
    c1 = threading.Thread(target=Consumer, args=('小明',))
    c2 = threading.Thread(target=Consumer, args=('小红',))
    c3 = threading.Thread(target=Consumer, args=('安安',))
    p.start()

    c1.start()
    c2.start()
    c3.start()

    p.join()
    c1.join()
    c2.join()
    c3.join()
    print(user)

祝学习愉快~

  • 如何像终止进程那样终止线程?


    本题中如果通过q.empty(),根据队列是否为空,来结束线程的话,


    如果做的速度比3个人吃的速度快3倍以上还行,否则,就会出现有人提早就终止了线程,实际上生产者还在作。


    如果生产者速度极慢time.sleep(5), 那么每个人可能就吃了一个,然后看队列空了就break了,后面生产者生产的就没人消费了。

    2022-10-26 00:12:26
  • 同学,你好!可以在获取队列.get()中添加timeout=n 。功能是:从队列中取数据,如果队列中没有数据,则等待n秒,n秒内没有取到数据,则会抛出异常,可在抛出异常中终止循环

    https://img1.sycdn.imooc.com//climg/63589e2e098116d006060708.jpg

    也可先生产出所有产品再用队列取,这也是一种方法。祝学习愉快~

    2022-10-26 10:42:47
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师