生产者消费者问题设计与实现Word下载.docx
《生产者消费者问题设计与实现Word下载.docx》由会员分享,可在线阅读,更多相关《生产者消费者问题设计与实现Word下载.docx(19页珍藏版)》请在冰豆网上搜索。
设计说明书规、合理。
进
度
安
排
起止日期
工作容
2015.6.23至2015.6.24
熟悉相关容
2015.6.25至2015.6.26
系统设计和实现
2015.6.27至2015.6.29
系统实现和撰写相关文档
主
要
参
考
资
料
1.《计算机操作系统》汤子瀛哲凤屏汤小丹主编电子科技大学.
2.《计算机操作系统概论》宏忠耀主编邮电大学.
3.《计算机操作系统基本知识》廖成阳主编电子工业.
4.《操作系统实现与设计》陆刚望能主编电子工业.
5.《java程序语言设计》丁振凡主编,薛清华副主编清华大学.
指导教师
意见
(签字):
年月日
系(教研室)主任意见
1.选题背景1
2.设计思路1
3.过程讨论1
4.结果分析11
5.结论12
参考文献13
致13
附录14
指导教师评语19
成绩评定19
1.选题背景
生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。
解决生产者/消费者问题的方法可分为两类:
(1)采用某种机制保护生产者和消费者之间的同步;
(2)在生产者和消费者之间建立一个管道。
第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。
第二种管道缓冲区不易控制,被传输数据对象不易于封装等,实用性不强。
因此本文只介绍同步机制实现的生产者/消费者问题。
同步问题核心在于:
如何保证同一资源被多个线程并发访问时的完整性。
常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。
Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。
在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。
2.设计思路
2.1.生产者—消费者问题是一种同步问题的抽象描述。
2.2计算机系统中的每个进程都可以消费或生产某类资源。
当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
2.3而当某个进程释放资源时,则它就相当一个生产者
3.过程论述
首先,生产者和消费者可能同时进入缓冲区,甚至可能同时读/写一个存储单元,将导致执行结果不确定。
这显然是不允许的。
所以,必须使生产者和消费者互斥进入缓冲区。
即某时刻只允许一个实体(生产者或消费者)访问缓冲区,生产者互斥消费者和其他任何生产者。
其次,生产者不能向满的缓冲区写数据,消费者也不能在空缓冲区中取数据,即生产者与消费者必须同步。
当生产者产生出数据,需要将其存入缓冲区之前,首先检查缓冲区中是否有“空”存储单元,若缓冲区存储单元全部用完,则生产者必须阻塞等待,直到消费者取走一个存储单元的数据,唤醒它。
若缓冲区有“空”存储单元,生产者需要判断此时是否有别的生产者或消费者正在使用缓冲区,若是有,则阻塞等待,否则,获得缓冲区的使用权,将数据存入缓冲区,释放缓冲区的使用权。
消费者取数据之前,首先检查缓冲区中是否存在装有数据的存储单元,若缓冲区为“空”,则阻塞等待,否则,判断缓冲区是否正在被使用,若正被使用,若正被使用,则阻塞等待,否则,获得缓冲区的使用权,进入缓冲区取数据,释放缓冲区的使用权。
3.1系统流程图
3.1.1生产者流程图:
3.1.2消费者流程图:
3.1.3主程序流程图:
3.1.4生产者:
ProducerThread
//定义生产者线程
classProducerThreadimplementsRunnable{
intproductNo=0;
//产品编号
intid;
//生产者ID
publicProducerThread(intid){
this.id=id;
}
publicvoidrun(){
while(isRun){
productNo++;
//生产产品
buffers.put(productNo,id);
//将产品放入缓冲队列
try{
Thread.sleep(1000);
}catch(Exceptione){
e.printStackTrace();
}
}
}
3.1.5消费者ConsumerThread
//定义消费者线程
classConsumerThreadimplementsRunnable{
//消费者ID
publicConsumerThread(intid){
}
buffers.get(id);
//从缓冲队列中取出产品
3.1.6缓冲区Buffer
classBuffer{
JTextAreata;
staticfinalintproductBufferNum=10;
//缓冲单元数
ProductBufferpBuffer[]=newProductBuffer[productBufferNum];
//缓冲队列
intin=0;
//缓冲单元指针,用于放产品get()
intout=0;
//缓冲单元指针,用于取产品put()
intconsumeProductNo;
//记录消费产品的编号
intusedBufferNum=0;
//记录缓冲队列已使用的缓冲单元个数
publicBuffer(JTextAreata){
this.ta=ta;
//初始化
for(intj=0;
j<
productBufferNum;
j++){
pBuffer[j]=newProductBuffer();
for(inti=0;
i<
i++){
pBuffer[i].product=-1;
pBuffer[i].hasProduct=false;
}
}
//取产品
publicsynchronizedvoidget(intid){
//缓冲队列空则等待
if(usedBufferNum<
=0){
try{
super.wait();
}catch(Exceptione){
e.printStackTrace();
consumeProductNo=pBuffer[out].product;
//取出产品
pBuffer[out].product=0;
//清空缓冲单元
pBuffer[out].hasProduct=false;
//置"
无产品"
标识
usedBufferNum--;
//输出本次取产品后缓冲队列的情况
ta.append("
消费者"
+id+"
将产品"
+consumeProductNo+"
从缓冲单元"
+out+"
取出,缓冲队列状态如下:
\n"
);
printBuffer();
out=(out+1)%productBufferNum;
//更新指针
//唤醒等待线程
super.notify();
//放产品
publicsynchronizedvoidput(intproductNo,intid){
//缓冲队列满则等待
if(usedBufferNum==productBufferNum){
pBuffer[in].product=productNo;
pBuffer[in].hasProduct=true;
//置“有产品”标识
usedBufferNum++;
///输出本次放入产品后,缓冲队列的情况
生产者"
+productNo+"
放入缓冲单元"
+in+"
,缓冲队列状态如下:
in=(in+1)%productBufferNum;
//打印缓冲队列当前情况
privatevoidprintBuffer(){
缓冲单元编号产品编号缓冲单元状态\n"
ta.append("
\t"
+i+"
+pBuffer[i].product+"
+pBuffer[i].hasProduct+"
/*
一个缓冲单元
*/
classProductBuffer{
intproduct;
//存放产品编号
booleanhasProduct;
//标识该缓冲区是否有产品,true有产品,false无产品
3.1.7图形界面createUI
publicvoidcreateUI()
{
JFrameframe=newJFrame("
生产者消费者"
JPanelpanel=newJPanel(newBorderLayout());
//ta.setBackground(Color.blue);
JScrollPanescrPane=newJScrollPane(ta);
panel.add(scrPane,BorderLayout.CENTER);
JButtonbutton=newJButton("
停止"
button.addActionListener(this);
panel.add(button,BorderLayout.SOUTH);
panel.setBackground(Color.BLUE);
frame.add(panel);
frame.setVisible(true);
frame.setSize(1000,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
3.1.8事件驱动actionPerformed
//按钮响应事件
publicvoidactionPerformed(ActionEvente){
isRun=false;
//控制线程结束
System.out.println("
4.结果分析
运行主程序得到一个GUI窗口,在文本域中输出结果,一共10个缓冲单元,三个生产者随机生产产品依次从0编号的缓冲区放入产品,消费者按照生产的先后顺序消费产品。
当缓冲单元有产品时,状态栏显示true,否则显示false。
并且当消费者取走产品后,产品编号会变成0.
5.结论
这次生产者与消费者之间的关系的实验我用Java语言编写的,用关键字synchronized来实现多个线程同步,用继承Thread来将生产者线程与消费者线程实例化。
其实,在做这个实验之前我的Java语言编程老师讲过这些知识,正好可以巩固Java的一些知识。
我还学过C++语言,这是大一下学期学的事了,我想要实现书上的P、V操作可以用C++语言来编写。
总之,通过该实验我更加清楚的认识到生产者与消费者这个经典问题实际上是线程同步问题的抽象描述,即计算机系统中的每个进程都可以消费(使用)或生产(释放)数据,进程释放数据相当于生产者,使用数据相当于消费者。
从Java的多线程机制出发,研究了操作系统中经典的同步问题—生产者消费者问题,提出了两种解决此问题的模型,及其Java解决方案。
提出的两个模型充分利用了Java中面向对象和管程机制,模拟了操作系统中进程同步的经典问题—生产者消费者问题。
在第一个模型中,我们按照生产者消费者问题典型的解决方案给出了Java解决模型;
在第二个模型中,我们分析了信号量mutex在问题中所起的作用,并为了提高缓冲区读写的效率,提出了将信号量mutex分为两个分别控制生产者和消费者的信号量,并讨论了此方案的可行性。
参考文献
[1]《计算机操作系统》汤子瀛哲凤屏汤小丹主编电子科技大学
[2]《计算机操作系统概论》宏忠耀主编邮电大学
[3]《计算机操作系统基本知识》廖成阳主编电子工业
[4]《操作系统实现与设计》陆刚望能主编电子工业
[5]《java程序语言设计》丁振凡主编,薛清华副主编清华大学
致
本组全体成员在此向所有关心我们的及帮助我们的老师和同学们致以最真诚的感。
在本次毕业设计中,尤其要感传健老师,对我们的课程设计时刻的关注,当我们遇到困难时给了我们很大的帮助,交给了我们团队的合作理念,使得我们能够按时完成这次的课程设计。
学生签名:
填表日期:
年月日
附录
importjava.awt.BorderLayout;
importjava.awt.Color;
importjava.awt.event.ActionEvent;
importjava.awt.event.ActionListener;
importjavax.swing.JButton;
importjavax.swing.JFrame;
importjavax.swing.JPanel;
importjavax.swing.JScrollPane;
importjavax.swing.JTextArea;
//importProducer_and_Customer.ConsumerThread;
//importProducer_and_Customer.ProducerThread;
*定义临界资源:
缓冲队列
**/
*生产者消费者问题实现(可以有多个生产者消费者)
publicclassProducer_and_CustomerimplementsActionListener{
privateJPaneljp[]=newJPanel[10];
booleanisRun=true;
//用于控制线程结束
JTextAreata=newJTextArea();
Bufferbuffers=newBuffer(ta);
staticfinalintproducerNum=3;
//生产者个数
staticfinalintconsumerNum=3;
//消费者个数
ProducerThreadproThread[]=newProducerThread[producerNum];
ConsumerThreadconThread[]=newConsumerThread[consumerNum];
Threadproducer[]=newThread[producerNum];
Threadconsumer[]=newThread[consumerNum];
publicProducer_and_Customer(){
createUI();
//createNewUI();
//创建多个生产者和消费者线程并开始执行
producerNum;
proThread[i]=newProducerThread(i+1);
producer[i]=newThread(proThread[i]);
producer[i].start();
consumerNum;
conThread[j]=newConsumerThread(j+1);
consumer[j]=newThread(conThread[j]);
consumer[j].start();
privatevoidcreateNewUI(){
JFrameframe=newJFrame("
Leo"
//创建界面
JPanelpanel=newJPanel(newBorderLayout