当前位置:文档之家› 生产者消费者问题设计与实现

生产者消费者问题设计与实现

操作系统课程设计任务书目录1.选题背景 (1)2.设计思路 (1)3.过程讨论 (1)4.结果分析 (7)5.结论 (8)参考文献 (9)致谢 (10)附录 (10)指导教师评语................................................... 错误!未定义书签。

成绩评定 .......................................................... 错误!未定义书签。

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//定义生产者线程class ProducerThread implements Runnable {int productNo = 0; //产品编号int id; //生产者IDpublic ProducerThread(int id){this.id = id;}public void run(){while(isRun){productNo++; //生产产品buffers.put(productNo, id); //将产品放入缓冲队列try{Thread.sleep(1000);}catch(Exception e){e.printStackTrace();}}}}3.1.5消费者 ConsumerThread//定义消费者线程class ConsumerThread implements Runnable {int id; //消费者IDpublic ConsumerThread(int id){this.id = id;}public void run(){while(isRun){buffers.get(id); //从缓冲队列中取出产品try{Thread.sleep(1000);}catch(Exception e){e.printStackTrace();}}}}3.1.6缓冲区Bufferclass Buffer {JTextArea ta;static final int productBufferNum = 10; //缓冲单元数ProductBuffer pBuffer[] = new ProductBuffer[productBufferNum]; //缓冲队列int in = 0; //缓冲单元指针,用于放产品get()int out = 0; //缓冲单元指针,用于取产品put()int consumeProductNo; //记录消费产品的编号int usedBufferNum = 0; //记录缓冲队列已使用的缓冲单元个数public Buffer (JTextArea ta){this.ta = ta;//初始化for(int j=0; j<productBufferNum; j++){pBuffer[j] = new ProductBuffer();}for(int i=0; i<productBufferNum; i++){pBuffer[i].product = -1;pBuffer[i].hasProduct = false;}}//取产品public synchronized void get(int id){//缓冲队列空则等待if(usedBufferNum <= 0){try{super.wait();}catch(Exception e){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();}//放产品public synchronized void put(int productNo, int id){//缓冲队列满则等待if(usedBufferNum == productBufferNum){try{super.wait();}catch(Exception e){e.printStackTrace();}}pBuffer[in].product = productNo; //放产品pBuffer[in].hasProduct = true; //置“有产品”标识usedBufferNum++;///输出本次放入产品后,缓冲队列的情况ta.append("生产者"+id+"将产品"+productNo+"放入缓冲单元"+in+",缓冲队列状态如下:\n");printBuffer();in=(in+1)%productBufferNum; //更新指针//唤醒等待线程super.notify();}//打印缓冲队列当前情况private void printBuffer(){ta.append(" 缓冲单元编号产品编号缓冲单元状态\n");for(int i=0; i<productBufferNum; i++){ta.append("\t"+i+"\t"+pBuffer[i].product+"\t"+pBuffer[i].hasProdu ct+"\n");}}}/*一个缓冲单元*/class ProductBuffer {int product; //存放产品编号boolean hasProduct; //标识该缓冲区是否有产品,true有产品,false 无产品}3.1.7图形界面createUIpublic void createUI(){JFrame frame = new JFrame("生产者消费者");JPanel panel = new JPanel(new BorderLayout());//ta.setBackground(Color.blue);JScrollPane scrPane = new JScrollPane(ta);panel.add(scrPane, BorderLayout.CENTER);JButton button = new JButton("停止");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//按钮响应事件public void actionPerformed(ActionEvent e){isRun = false; //控制线程结束System.out.println("停止");}4.结果分析运行主程序得到一个GUI窗口,在文本域中输出结果,一共10个缓冲单元,三个生产者随机生产产品依次从0编号的缓冲区放入产品,消费者按照生产的先后顺序消费产品。

当缓冲单元有产品时,状态栏显示true,否则显示false。

并且当消费者取走产品后,产品编号会变成0.5.结论这次生产者与消费者之间的关系的实验我用Java语言编写的,用关键字synchronized来实现多个线程同步,用继承Thread来将生产者线程与消费者线程实例化。

相关主题