生产者—消费者问题:多线程访问的一个经典案例,即按面向对象的思想来分析问题的话,这个问题涉及四个对象,生产者Procedure、消费者Consumer、产品Product、仓库WareHouse。下面以一个简单的例子来进行实现。
一、产品Product
每个产品有一个属性id,这个id值由生产者赋予。即生产者调用产品的构造方法来设置该属性id。
class Product
{ int id=0;
Product(int id){
this.id=id;}
public String toString(){
return "Product: "+this.id;
}
}
二、仓库WareHouse
1、仓库有两个属性:库存num、容量,库存用int表示,初始化为0;容量用数组的长度表示。库存即该产品数组中的前num个产品。
2、两个方法:增加库存add和减少库存del。在add中将传入的产品参数放入库存数组,将库存量加一。减少库存del中将库存量num减一、并返回消费产品。
3、在add和del方法中,执行前后应该检查库存,若执行add方法,当库存为库存的容量时,使得当前线程wait,该线程(为生产者对象)放弃锁。直到当消费者线程执行del使得库存量小于仓库容量时,唤醒当前进程,重新获得锁,继续执行生产add。若执行del,当库存为0时,使得当前进程wait,释放锁,直到生产者进程获取锁之后执行add后库存大于0,此时唤醒进程重新获得锁,执行消费del。
4、在add和del方法中,可能出现多个生产者和多个消费者同时访问库存并执行add和del,所以这两个方法都应设置为同步方法。
class WareHouse
{ int num=0;
Product[] list=new Product[10];
public synchronized void add(Product p){
while(num==list.length-1){
try{this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
this.notifyAll();
list[num]=p;
num++;
}
public synchronized Product del(){
while(num==0){
try{this.wait();
}catch(Exception e){
e.printStackTrace();
}
}
this.notifyAll();
num--;
return list[num];
}
}
三、生产者Procedure
生产者构造方法传入一个WareHouse参数生成生产者。每个Produre都是一个进程,所以实现Runnable接口和相应的run方法,在run方法中,每个Procedure可以生产10件产品。
class Procedure implements Runnable
{
WareHouse wh=null;
Procedure(WareHouse wh){
this.wh = wh;}
public void run(){
for(int i=0;i<10;i++){
Product pp =new Product(i);
wh.add(pp);
System.out.println(Thread.currentThread()+"生产了:"+pp);
}
}
}
四、消费者Consumer
消费者由传入一个WareHouse参数构造。同理,每个Consumer也实现了Runnable接口和run方法,在run方法中,设定每个消费者可以消费5件产品。
class Consumer implements Runnable
{
WareHouse wh=null;
Consumer(WareHouse wh){
this.wh = wh;}
public void run(){
for(int i=0;i<5;i++){
Product ppp= wh.del();
System.out.println(Thread.currentThread()+"消费了:"+ppp);
}
}
}
五、测试类:在main方法中首先建立一个WareHouse对象,然后利用WareHouse对象新建Procedure对象和Consumer对象各俩,最后利用Procedure和Consumer对象新建四个进程,然后start这四个进程。
public class P_C
{
public static void main(String[] args)
{
WareHouse wh =new WareHouse();
Procedure p1=new Procedure(wh);
Procedure p2=new Procedure(wh);
Consumer m1 = new Consumer(wh);
Consumer m2 =new Consumer(wh);
Thread t1 =new Thread(p1);
Thread t2 =new Thread(p2);
Thread t3 =new Thread(m1);
Thread t4 =new Thread(m2);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
分享到:
相关推荐
Qt入门练习项目——生产者消费者模型 Qt入门练习项目源码,通过本项目从而了解Qt,进行一个简单的入门。 本文件是对应项目源码,希望多多交流。
基于Linux C++的条件变量实现的生产者消费者模型,旨在进一步帮助读者理解条件变量的使用。
java生产者消费者模型
生产者,消费者,线程同步,模型,锁
内容概要:操作系统实验,前端 vue3 + vite3 + pinia + ant design vue实现简易的生产者消费者模型,可以通过输入表单的形式手动调节生产者的消费速率和消费者的消费速率的形式,实现生产者消费者模型的可视化效果。...
所谓的生产者消费者模型,是通过一个容器来解决生产者和消费者的强耦合问题。通俗的讲,就是生产者在不断的生产,消费者也在不断的消费,可是消费者消费的产品是生产者生产的,这就必然存在一个中间容器,我们可以把...
LinuxC语言实现生产者和消费者模型LinuxC语言实现生产者和消费者模型LinuxC语言实现生产者和消费者模型LinuxC语言实现生产者和消费者模型LinuxC语言实现生产者和消费者模型LinuxC语言实现生产者和消费者模型LinuxC...
生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和...
多线程实现生产者消费者模型:锁(Lock)、信号量(Semaphore、BoundedSemaphore)、条件(Condition)、队列(Queue)、事件(Event) 多进程程实现生产者消费者模型:信号量(Semaphore)、条件(Condition)、...
LINUX下的生产者消费者模型算法 利用进程模拟生产者消费者,利用共享存储区模拟缓冲区
大学计算机专业,操作系统实验报告,生产者消费者模型模拟进程调度
利用线程间的通信主要是因为当多个线程同时对一个对象进行访问的时候,多个线程之间是一个协助的关系,举个例子就是今天要说的生产这和消费者模型。
操作系统实验课实现的生产者消费者模型图形化演示。通过“企鹅吃苹果”这个小故事吧,苹果是生产者生产出来的,而企鹅是消费者。可以调节生产和消费的速度,也可以暂停程序方便演示。用C++实现的,使用的是纯粹的API...
这是本人学习labview生产者消费者模型时,收藏的资料,里面包含生产消费者模型的文档介绍和例程,保证资源真实有效,例程能跑。
内容概要:基于QT Creator环境的多线程编程验证互斥的原理,通过使用semaphore,mutex等控制变量,实现对生产者消费者模型的真实模拟。 适合人群:初学操作系统的学生 能学到什么:调用了Qt多线程类库QThread进行...
java 多线程生产者消费者模型demo
wpf窗体多线程实现生产者消费者模型(利用信号量),工作线程利用回调函数改变窗体线程的控件。
NULL 博文链接:https://aspnetdb.iteye.com/blog/1123894
什么是生产者消费者模型 在 工作中,大家可能会碰到这样一种情况:某个模块负责产生数据,这些数据由另一个模块来负责处理(此处的模块是广义的,可以是类、函数、线程、进程等)。产 生数据的模块,就形象地称为...
用Qt实现的生产者消费者模型(多进程),操作系统课程作业。 4消费者,4生产者,12缓冲区,可视化展示。