生产者消费者模型是一种经典的多线程或并发编程概念,用于解决资源共享问题。在这个模型中,生产者负责创建数据,而消费者则负责处理这些数据。Python 提供了几种实现这一模型的方法,本篇主要介绍了两种:使用 `queue` 模块和使用 `yield` 协程。
### 1. 使用 `queue` 模块实现
#### 1.1 基本原理
在 Python 中,`queue` 模块提供了一种线程安全的数据结构,可以用来作为生产者和消费者之间的缓冲区。生产者将数据放入队列,消费者从队列中取出数据。当队列满时,生产者将阻塞,直到队列有空位;当队列为空时,消费者也会阻塞,直到队列中有新的数据。
#### 1.2 示例代码
在给出的示例中,`queue.Queue(maxsize=10)` 创建了一个最大容量为 10 的队列。`Producer` 线程不断向队列中放入 '骨头',`Consumer` 线程从队列中取出并消耗这些 '骨头'。`time.sleep()` 用于模拟生产与消费的过程,使示例更具现实感。
```python
import threading
import queue
import time
q = queue.Queue(maxsize=10)
def Producer(name):
count = 1
while True:
q.put('骨头{}'.format(count))
print('生产了骨头', count)
count += 1
time.sleep(1)
def Consumer(name):
while True:
print('[{}] 取到[{}] 并且吃了它...'.format(name, q.get()))
time.sleep(1)
p = threading.Thread(target=Producer, args=('shenchanzhe',))
c = threading.Thread(target=Consumer, args=('xiaofeizhe01',))
c1 = threading.Thread(target=Consumer, args=('xiaofeizhe02',))
p.start()
c.start()
c1.start()
```
### 2. 使用 `yield` 协程实现
#### 2.1 基本原理
`yield` 关键字用于创建生成器(generator),生成器是一种特殊的迭代器,可以在运行过程中暂停并保存状态。这种方式下,生产者和消费者不再通过线程进行同步,而是通过生成器的 `send()` 方法传递数据,减少了线程上下文切换的开销。
#### 2.2 示例代码
在 `consumer` 函数中,`yield` 用于挂起函数的执行,等待外部调用 `send()` 来传递数据。`producer` 函数创建了两个消费者,并通过 `send()` 方法交替向它们发送数据。
```python
import time
def consumer(name):
print('{}准备吃包子了!'.format(name))
while True:
baozi = yield
print('包子【{}】来了,被【{}】吃了'.format(baozi, name))
def producer(name):
c1 = consumer('A')
c2 = consumer('B')
c1.__next__()
c2.__next__()
print('老子开始做包子了')
for i in range(1, 10):
time.sleep(1)
print('三秒做了两个包子')
c1.send(i)
c2.send(i + 1)
```
### 总结
这两种模式的生产者消费者模型在 Python 中都有其应用场景。`queue` 模块的实现更适用于多线程环境,能够有效地处理并发问题,而 `yield` 协程的实现则提供了更轻量级的同步机制,适用于低延迟、高效率的需求。根据具体项目需求,开发者可以选择适合的方式来实现生产者消费者模型。