生产者消费者问题设计与实现_第1页
生产者消费者问题设计与实现_第2页
生产者消费者问题设计与实现_第3页
生产者消费者问题设计与实现_第4页
生产者消费者问题设计与实现_第5页
已阅读5页,还剩9页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

。选题背景生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类:(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{ intid;//消费者ID publicConsumerThread(intid){ this。id=id; } publicvoidrun(){ while(isRun){ buffers.get(id);//从缓冲队列中取出产品 try{ Thread.sleep(1000); }catch(Exceptione){ e。printStackTrace(); } } } }3。1.6缓冲区BufferclassBuffer{ 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〈productBufferNum;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){ try{ super.wait(); }catch(Exceptione){ e.printStackTrace(); } } pBuffer[in].product=productNo;//放产品 pBuffer[in]。hasProduct=true;//置“有产品”标识 usedBufferNum++; ///输出本次放入产品后,缓冲队列的情况 ta。append(”生产者”+id+"将产品"+productNo+”放入缓冲单元"+in+",缓冲队列状态如下:\n”); printBuffer(); in=(in+1)%productBufferNum;//更新指针 //唤醒等待线程 super.notify(); } //打印缓冲队列当前情况 privatevoidprintBuffer(){ ta.append(”缓冲单元编号产品编号缓冲单元状态\n"); for(inti=0;i<productBufferNum;i++){ ta。append("\t”+i+"\t"+pBuffer[i].product+"\t"+pBuffer[i]。hasProduct+"\n"); } }}/*一个缓冲单元*/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分为两个分别控制生产者和消费者的信号量,并讨论了此方案的可行性.参考文献《计算机操作系统》汤子瀛哲凤屏汤小丹主编西安电子科技大学出版社《计算机操作系统概论》陈宏杨忠耀主编重庆邮电大学出版社《计算机操作系统基本知识》廖成崔阳主编电子工业出版社《操作系统实现与设计》陆刚望能主编电子工业出版社《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;/**定义临界资源:缓冲队列**/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<productBufferNum;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){ try{ super。wait(); }catch(Exceptione){ e.printStackTrace(); } } pBuffer[in].product=productNo;//放产品 pBuffer[in].hasProduct=true;//置“有产品”标识 usedBufferNum++; ///输出本次放入产品后,缓冲队列的情况 ta。append(”生产者”+id+”将产品”+productNo+”放入缓冲单元"+in+”,缓冲队列状态如下:\n"); printBuffer(); in=(in+1)%productBufferNum;//更新指针 //唤醒等待线程 super。notify(); } //打印缓冲队列当前情况 privatevoidprintBuffer(){ ta。append(”缓冲单元编号产品编号缓冲单元状态\n"); for(inti=0;i<productBufferNum;i++){ ta.append(”\t"+i+”\t"+pBuffer[i].product+”\t”+pBuffer[i].hasProduct+”\n"); } }}/*一个缓冲单元*/classProductBuffer{ intproduct;//存放产品编号 booleanhasProduct;//标识该缓冲区是否有产品,true有产品,false无产品}/**生产者消费者问题实现(可以有多个生产者消费者)**/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(); //创建多个生产者和消费者线程并开始执行 for(inti=0;i〈producerNum;i++){ proThread[i]=newProducerThread(i+1); producer[i]=newThread(proThread[i]); producer[i].start(); } for(intj=0;j〈consumerNum;j++){ conThread[j]=newConsumerThread(j+1); consumer[j]=newThread(conThread[j]); consumer[j].start(); } } privatevoidcreateNewUI(){ JFrameframe=newJFrame(”Leo”); } //创建界面 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(100

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论