生产者-消费者问题(计算机系统中的许多问题都可归结为此问题)描述如下:生产者与消费者可以通过一个环形缓冲池联系起来,环形缓冲池由几个大小相等的缓冲块组成,每个缓冲块容纳一个产品。每个生产者可不断地每次往缓冲池中送一个生产产品,而每个消费者则可不断地每次从缓冲池中取出一个产品。 编写程序模拟多个生产者和多个消费者共享缓冲池的生产和消费过程。 要求: 1. 设计信号量用于进行生产者-消费者、生产者-生产者、消费者-消费者之间的同步控制; 2. 创建多个(不少于5个)进程或者线程模拟生产者和消费者; 3. 缓冲池大小定义在10-20,缓冲块中的产品为数据; 4. 程序运行结果能实时显示缓冲池中生产和消费产品的过程,包括断点、推进时间、次序等,编程语言选用Java。5.要求代码添加注释。
时间: 2024-02-13 22:05:08 浏览: 74
生产者-消费者问题(处理机调度进行模拟)
好的,我明白了您的问题。这是一个经典的生产者-消费者问题,需要使用信号量进行同步控制。下面是Java代码的实现,注释已经添加在代码中,您可以参考下:
```java
import java.util.concurrent.Semaphore;
public class ProducerConsumer {
// 定义缓冲池大小
private static final int BUFFER_SIZE = 10;
// 定义缓冲块,用于存储产品
private static final Object[] buffer = new Object[BUFFER_SIZE];
// 定义信号量,用于同步控制
private static final Semaphore mutex = new Semaphore(1); // 互斥信号量
private static final Semaphore empty = new Semaphore(BUFFER_SIZE); // 空闲缓冲块信号量
private static final Semaphore full = new Semaphore(0); // 产品缓冲块信号量
public static void main(String[] args) {
// 创建多个生产者和消费者线程
for (int i = 1; i <= 5; i++) {
new Thread(new Producer(i)).start();
new Thread(new Consumer(i)).start();
}
}
// 生产者线程
static class Producer implements Runnable {
private final int id;
public Producer(int id) {
this.id = id;
}
@Override
public void run() {
try {
while (true) {
// 生成产品
Object product = produceProduct();
// 等待空闲缓冲块
empty.acquire();
// 等待互斥锁
mutex.acquire();
// 将产品放入缓冲池
buffer[getBufferIndex()] = product;
System.out.println("Producer " + id + " produced " + product + " at " + getBufferIndex());
// 释放互斥锁
mutex.release();
// 增加产品缓冲块信号量
full.release();
// 休眠一段时间,模拟生成产品的耗时
Thread.sleep((long) (Math.random() * 1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 生成产品
private Object produceProduct() {
return new Object();
}
// 获取缓冲块的索引
private int getBufferIndex() {
for (int i = 0; i < BUFFER_SIZE; i++) {
if (buffer[i] == null) {
return i;
}
}
return -1;
}
}
// 消费者线程
static class Consumer implements Runnable {
private final int id;
public Consumer(int id) {
this.id = id;
}
@Override
public void run() {
try {
while (true) {
// 等待产品缓冲块
full.acquire();
// 等待互斥锁
mutex.acquire();
// 从缓冲池中取出产品
Object product = buffer[getBufferIndex()];
buffer[getBufferIndex()] = null;
System.out.println("Consumer " + id + " consumed " + product + " from " + getBufferIndex());
// 释放互斥锁
mutex.release();
// 增加空闲缓冲块信号量
empty.release();
// 休眠一段时间,模拟消费产品的耗时
Thread.sleep((long) (Math.random() * 1000));
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 获取缓冲块的索引
private int getBufferIndex() {
for (int i = 0; i < BUFFER_SIZE; i++) {
if (buffer[i] != null) {
return i;
}
}
return -1;
}
}
}
```
代码中使用了三个信号量:`mutex`用于实现互斥访问缓冲池,`empty`表示空闲缓冲块的数量,`full`表示已经存储产品的缓冲块数量。当一个生产者生成一个产品时,需要先等待`empty`信号量,表示有空闲的缓冲块可以存储产品,然后再等待`mutex`信号量,保证只有一个生产者可以进入临界区,将产品存储到缓冲池中,并释放`mutex`信号量,表示临界区已经访问完毕,增加`full`信号量,表示已经存储了一个产品。当一个消费者需要取出一个产品时,需要先等待`full`信号量,表示缓冲池中有产品可以取出,然后再等待`mutex`信号量,保证只有一个消费者可以进入临界区,将产品从缓冲池中取出,并释放`mutex`信号量,表示临界区已经访问完毕,增加`empty`信号量,表示又有一个空闲的缓冲块。每个生产者和消费者都会不断地执行这个过程,直到程序结束。在每次生成产品和消费产品的过程中,都会随机休眠一段时间,模拟生成和消费产品的耗时。
程序运行时,会实时显示缓冲池中生产和消费产品的过程,包括断点、推进时间、次序等。
阅读全文