目录
前言
消费者问题是操作系统中典型的进程同步互斥问题,(英语:Producer-Consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个进程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程“生产者”(Producer)和“消费者”(Consumer)在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。问题的约束条件是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中为空时消耗数据。
一、实验要求
- 互斥信号量和资源信号量的使用
- 互斥信号量初始值为1来表示(同步于操作系统书),同步信号量用0表示(本文没有涉及到)。
- 最大存放空间为10。
- 消费者不可以在没有产品的时候进行消费。
- 消费者和生产者是两个线程
- 生产和消费这两个线程执行时,生产者或者消费者不会一直执行相应的方法。(是穿插着来的)
二、步骤
1.主类
代码如下(示例):
- 实例化俩个实现Runnable接口的对象
import com.os.util.Consumer;
import com.os.util.Producer;
import com.os.util.Supermarket;
/**
* 主类
*/
public class Main {
public static void main(String[] args) {
Supermarket supermarket = new Supermarket();
Consumer consumer = new Consumer(supermarket);
Producer producer = new Producer(supermarket);
Thread
t1 = new Thread(consumer,"消费者"),
t2 = new Thread(producer,"生产者");
t1.start();
t2.start();
}
}
2.消费者
代码如下(示例):
- 死循环执行消费方法
/**
* 消费者
*/
public class Consumer implements Runnable{
private Supermarket supermarket;
public Consumer(Supermarket supermarket) {
this.supermarket = supermarket;
}
@Override
public void run() {
while (true) {
supermarket.consume();
}
}
}
3.生产者
代码如下(示例):
- 死循环执行生产方法
/**
*生产者
*/
public class Producer implements Runnable{
private Supermarket supermarket;
public Producer(Supermarket supermarket) {
this.supermarket = supermarket;
}
@Override
public void run() {
while (true) {
supermarket.product();
}
}
}
4.超市
/** * 互斥信号量 * 1:生产者正在执行此时消费者等待,生产者执行完毕之后,消费者再去执行。 * 0:消费者正在执行此时生产者等待,消费者执行完毕之后,生产者再去执行。 * * wait()和 notify()是一对互斥锁 相对于wait()和signal() * wait()是进行等待,当前线程处在阻塞状态 * notify()是唤醒线程 */
代码如下(示例):
public class Supermarket {
private static int mutex = 1; //互斥信号量
private static final int max = 10; //可放最大空间
private int count; //统计产品数量
public synchronized void product() {
if (mutex == 0 && this.count >= max) {
try {
this.wait();//线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
}//互斥信号量为0 且生产的数量小于超市可放的最大数量()
else {
count++;//生产产品
System.out.println(Thread.currentThread().getName() + "生产 +1,剩余:" + count);
this.notify();//唤醒线程
mutex = 0;//消费者进行消费
try {
Thread.sleep(500);//避免当前线程再次进入该方法,执行线程等待半秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public synchronized void consume() {
if (this.count == 0 && mutex==1) {
try {
this.wait();//线程等待
} catch (InterruptedException e) {
e.printStackTrace();
}
//mutex=0且 count !=0
} else {
count--;//消费产品
System.out.println(Thread.currentThread().getName() + "消费 -1,剩余:" + count);
this.notify();//唤醒线程
mutex = 1;
try {
Thread.sleep(500);//避免当前线程再次进入该方法,执行线程等待半秒
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
三、运行结果
- 可能每次的运行结果不用,但是都满足实验要求。