编写程序,创建生产者线程和消费者线程以及大小为5的缓冲区。生产者每隔1至3秒钟就生产一个数字并放入缓冲区,如果缓冲区已满则等待;消费者每隔1至3秒就从缓冲区里取出生产日期较早的数字进行消费,如果缓冲区已空就等待。运行程序,观察并理解缓冲区内数字变化以及生产者线程和消费者线程之间的同步。
时间: 2023-11-27 14:50:09 浏览: 69
生产者消费者模型示例源码
5星 · 资源好评率100%
以下是一个简单的 Python 实现,使用了 threading 和 queue 模块:
```python
import threading
import queue
import time
import random
# 缓冲区大小为5
BUFFER_SIZE = 5
# 生产者和消费者线程数量
NUM_PRODUCERS = 2
NUM_CONSUMERS = 3
# 全局计数器,用于记录生产的数字
counter = 0
# 锁对象,用于保证多线程访问 counter 的安全性
counter_lock = threading.Lock()
# 缓冲区队列对象,最大长度为 BUFFER_SIZE
buffer = queue.Queue(BUFFER_SIZE)
def producer():
global counter
while True:
# 随机等待1至3秒钟
time.sleep(random.randint(1, 3))
# 生产数字
with counter_lock:
num = counter
counter += 1
print(f"生产者 {threading.current_thread().name} 生产了数字 {num}")
# 将数字放入缓冲区
buffer.put(num)
print(f"缓冲区中的数字为 {list(buffer.queue)}")
def consumer():
while True:
# 随机等待1至3秒钟
time.sleep(random.randint(1, 3))
# 从缓冲区取出数字
num = buffer.get()
print(f"消费者 {threading.current_thread().name} 消费了数字 {num}")
# 处理完数字后,通知缓冲区
buffer.task_done()
# 创建生产者线程和消费者线程
producers = []
consumers = []
for i in range(NUM_PRODUCERS):
t = threading.Thread(target=producer, name=f"生产者{i+1}")
t.daemon = True
producers.append(t)
for i in range(NUM_CONSUMERS):
t = threading.Thread(target=consumer, name=f"消费者{i+1}")
t.daemon = True
consumers.append(t)
# 启动所有线程
for t in producers + consumers:
t.start()
# 等待所有线程结束
for t in producers + consumers:
t.join()
print("所有线程结束")
```
在上面的代码中,我们使用了一个全局计数器 `counter` 来记录生产的数字,使用锁对象 `counter_lock` 来保证多线程访问 `counter` 的安全性。我们还创建了一个缓冲区队列对象 `buffer`,最大长度为 `BUFFER_SIZE`,用于存放生产者生产的数字。当生产者生产数字时,将其放入缓冲区;当消费者消费数字时,从缓冲区取出生产日期较早的数字进行消费。注意,当消费者处理完数字后,需要调用 `buffer.task_done()` 方法通知缓冲区,以便于其他线程继续工作。
在运行程序时,我们可以观察到生产者和消费者线程之间的同步关系,以及缓冲区内数字的变化。例如:
```
生产者 生产者1 生产了数字 0
缓冲区中的数字为 [0]
消费者 消费者1 消费了数字 0
生产者 生产者2 生产了数字 1
缓冲区中的数字为 [1, 2, 3, 4, 5]
消费者 消费者3 消费了数字 1
生产者 生产者2 生产了数字 2
缓冲区中的数字为 [2, 3, 4, 5]
消费者 消费者2 消费了数字 2
```
在这个例子中,我们使用了两个生产者线程和三个消费者线程,缓冲区大小为5。生产者每隔1至3秒钟就生产一个数字并放入缓冲区,消费者每隔1至3秒就从缓冲区里取出生产日期较早的数字进行消费。我们可以看到,缓冲区中的数字在不断变化,而生产者和消费者之间的同步关系得到了保证。
阅读全文