python—生产者消费者模型

python-生产者消费者模型

生产者和消费者模式是多线程开发中经常见到的一种模式。生产者的线程专门用来生产一些数据,然后存放到一个中间的变量中。消费者再从这个中间的变量中取出数据进行消费。通过生产者和消费者模式,可以让代码达到高内聚低耦合的目标,程序分工更加明确,线程更加方便管理。下面分别展示Lock版本和 Condition版本的生产者和消费者模型(生产者只能生产10次)。

Lock版本的生产者和消费者模式:

import threading
import random
import time

gMoney = 0
gLock = threading.Lock()
gTimes = 0


class Producer(threading.Thread):
    def run(self) -> None:   # 箭头代表函数值返回的是None
        global gMoney  # 更改了全局变量需要声明
        global gTimes
        while True:
            time.sleep(1)
            gLock.acquire()  # 上锁
            if gTimes >= 10:  # 生产者只能生产10次
                gLock.release()  # 在退出循环之前释放锁
                break  # 退出循环
            money = random.randint(0, 100)
            gMoney += money
            gTimes += 1
            print("%s生产了%d元钱"%(threading.current_thread().name,money))
            gLock.release()  # 释放锁



class Consumer(threading.Thread):
    def run(self) -> None:
        global gMoney
        while True:
            time.sleep(1)
            gLock.acquire()
            money = random.randint(0,100)
            if gMoney >= money:  # 判断钱够不够
                gMoney -= money
                print("%s消费了%d元钱"%(threading.current_thread().name,money))
            else:
                if gTimes >= 10:  # 生产者已经不再生产
                    gLock.release()
                    break
                print("%s想消费%d元钱,但是余额只有%d"%(threading.current_thread().name,money,gMoney))
            gLock.release()


def main():
    for x in range(5):  # 创建5个生产者线程
        th = Producer(name="生产者%d号"%x)
        th.start()

    for x in range(5):  # 创建5个消费者线程
        th = Consumer(name="消费者%d号"%x)
        th.start()

if __name__ == '__main__':
    main()

输出结果:

生产者0号生产了4元钱
生产者1号生产了22元钱
生产者3号生产了6元钱
消费者0号想消费72元钱,但是余额只有32
生产者4号生产了53元钱
生产者2号生产了30元钱
消费者4号消费了1元钱
消费者1号消费了39元钱
消费者3号消费了58元钱
消费者2号想消费40元钱,但是余额只有17
生产者0号生产了80元钱
消费者0号消费了71元钱
生产者3号生产了84元钱
生产者1号生产了93元钱
消费者3号消费了20元钱
消费者4号消费了92元钱
生产者2号生产了22元钱
消费者2号消费了31元钱
生产者4号生产了73元钱
消费者1号消费了41元钱
消费者0号消费了8元钱
消费者3号消费了13元钱
消费者4号消费了0元钱
消费者2号消费了72元钱
消费者0号消费了1元钱

Process finished with exit code 0

Condition版本的生产者和消费者模式:

Lock版本的生产者与消费者模式可以正常的运行。但是存在一个不足,在消费者中,总是通过while True死循环并且上锁的方式去判断钱够不够。上锁是一个很耗费CPU资源的行为。因此这种方式不是最好的。还有一种更好的方式便是使用threading.Condition来实现。threading.Condition可以在没有数据的时候处于阻塞等待状态。一旦有合适的数据了,还可以使用notify相关的函数来通知其他处于等待状态的线程。这样就可以不用做一些无用的上锁和解锁的操作。可以提高程序的性能。首先对threading.Condition相关的函数做个介绍,threading.Condition类似threading.Lock,可以在修改全局数据的时候进行上锁,也可以在修改完毕后进行解锁。以下将一些常用的函数做个简单的介绍:

  1. acquire:上锁。
  2. release:解锁。
  3. wait:将当前线程处于等待状态,并且会释放锁。可以被其他线程使用notify和notify_all函数唤醒。被唤醒后会继续等待上锁,上锁后继续执行下面的代码。
  4. notify:通知某个正在等待的线程,默认是第1个等待的线程。
  5. notify_all:通知所有正在等待的线程。notify和notify_all不会释放锁。并且需要在release之前调用。

代码如下:

import threading
import random
import time

gMoney = 0
gCondition = threading.Condition()
gTimes = 0


class Producer(threading.Thread):
    def run(self) -> None:
        global gMoney
        global gTimes
        while True:
            time.sleep(1)
            gCondition.acquire()
            if gTimes >= 10:
                gCondition.release()
                break
            money = random.randint(0, 100)
            gMoney += money
            gTimes += 1
            print("%s生产了%d元钱,剩余%d元钱"%(threading.current_thread().name,money,gMoney))
            gCondition.notify_all()
            gCondition.release()



class Consumer(threading.Thread):
    def run(self) -> None:
        global gMoney
        while True:
            time.sleep(1)
            gCondition.acquire()
            money = random.randint(0,100)
            while gMoney < money:
                if gTimes >= 10:
                    print("%s想消费%d元钱,但是余额只有%d元钱了,并且生产者已经不再生产了!"%(threading.current_thread().name,money,gMoney))
                    gCondition.release()
                    return  # 一次性将整个函数全部返回
                print("%s想消费%d元钱,但是余额只有%d元钱了,消费失败!"%(threading.current_thread().name,money,gMoney))
                gCondition.wait()
            gMoney -= money
            print("%s消费了%d元钱,剩余%d元钱"%(threading.current_thread().name,money,gMoney))
            gCondition.release()



def main():
    for x in range(5):
        th = Producer(name="生产者%d号"%x)
        th.start()

    for x in range(5):
        th = Consumer(name="消费者%d号"%x)
        th.start()

if __name__ == '__main__':
    main()

输出结果:

生产者2号生产了18元钱,剩余18元钱
生产者3号生产了71元钱,剩余89元钱
消费者3号消费了16元钱,剩余73元钱
生产者4号生产了16元钱,剩余89元钱
生产者1号生产了52元钱,剩余141元钱
消费者4号消费了93元钱,剩余48元钱
消费者0号想消费98元钱,但是余额只有48元钱了,消费失败!
消费者1号想消费49元钱,但是余额只有48元钱了,消费失败!
消费者2号消费了18元钱,剩余30元钱
生产者0号生产了31元钱,剩余61元钱
消费者0号想消费98元钱,但是余额只有61元钱了,消费失败!
消费者1号消费了49元钱,剩余12元钱
消费者4号想消费28元钱,但是余额只有12元钱了,消费失败!
生产者2号生产了42元钱,剩余54元钱
消费者0号想消费98元钱,但是余额只有54元钱了,消费失败!
生产者4号生产了31元钱,剩余85元钱
消费者0号想消费98元钱,但是余额只有85元钱了,消费失败!
生产者1号生产了52元钱,剩余137元钱
消费者0号消费了98元钱,剩余39元钱
消费者4号消费了28元钱,剩余11元钱
消费者3号想消费76元钱,但是余额只有11元钱了,消费失败!
生产者3号生产了87元钱,剩余98元钱
生产者0号生产了59元钱,剩余157元钱
消费者3号消费了76元钱,剩余81元钱
消费者1号消费了5元钱,剩余76元钱
消费者2号消费了7元钱,剩余69元钱
消费者3号消费了55元钱,剩余14元钱
消费者4号想消费55元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者1号想消费94元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者0号想消费50元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者2号想消费52元钱,但是余额只有14元钱了,并且生产者已经不再生产了!
消费者3号想消费59元钱,但是余额只有14元钱了,并且生产者已经不再生产了!

Process finished with exit code 0

生产者消费者模型是学习多线程的基础,我还写过一个多线程的案例——多线程下载王者荣耀高清壁纸(过程超详细)这是链接:https://blog.csdn.net/liumengqi11/article/details/112519483,核心也是生产者消费者模型,大家可以看完这篇文章后再看一下那个案例,对理解多线程有很大帮助!!
♥♥♥希望对大家有所帮助!♥♥♥

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
生产者消费者模型是一种经典的并发编程模型,用于解决生产者和消费者之间的数据交换问题。在 Python 中,可以使用多线程或多进程实现生产者消费者模型。 下面是一个使用 Python 多线程实现生产者消费者模型的示例代码: ```python import threading import queue import time # 定义一个线程安全的队列 q = queue.Queue(maxsize=10) # 定义一个生产者线程 class Producer(threading.Thread): def run(self): while True: # 如果队列未满,则向队列中添加数据 if not q.full(): item = time.strftime('%H:%M:%S', time.localtime()) q.put(item) print(f'生产者 {self.name} 生产了 {item}') time.sleep(1) # 定义一个消费者线程 class Consumer(threading.Thread): def run(self): while True: # 如果队列不为空,则从队列中取出数据 if not q.empty(): item = q.get() print(f'消费者 {self.name} 消费了 {item}') time.sleep(2) if __name__ == '__main__': # 创建两个生产者线程和三个消费者线程 producers = [Producer() for i in range(2)] consumers = [Consumer() for i in range(3)] # 启动所有线程 for p in producers: p.start() for c in consumers: c.start() # 等待所有线程结束 for p in producers: p.join() for c in consumers: c.join() ``` 在上面的代码中,我们定义了一个线程安全的队列 `q`,并定义了一个生产者线程 `Producer` 和一个消费者线程 `Consumer`。生产者线程不断向队列中添加数据,消费者线程不断从队列中取出数据。我们创建了两个生产者线程和三个消费者线程,并启动所有线程。最后,我们使用 `join()` 方法等待所有线程执行完毕。运行上面的代码,可以看到生产者不断生产数据,消费者不断消费数据,实现了生产者消费者模型

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值