资源描述
操作系统 课程设计任务书
学 院
计算机与信息工程
专 业
计算机科学与技术
课程名称
操作系统
题 目
生产者消费者问题设计与实现
完成期限
自2015年6月23日至2015年6月29日共1周
内
容
及
任
务
一、项目的目的
1。理生产者消费者问题基本概念和工作原理,以及实现技术;
2.理解并掌握生产者消费者问题相关算法,以及它的实现方法;
3.掌握在eclipse环境下,系统开发的基本步骤和方法;
4。掌握在eclipse环境下,设计和开发一个简单的生产者消费者问题系统来模拟操作系统中生产者消费者问题。
二、项目任务的主要内容和要求
1。精读并理解和掌握生产者消费者问题;
2.编写程序来模拟生产者消费者问题的实现;
3。编写应用程序测试生产者消费者问题,并显示结果。
三、项目设计(研究)思路
本课程设计的基本思路是,首先理解和掌握生产者消费者问题的基本思想和原理,然后根据理解的基本思想和原理编程实现生产者消费者问题,最后通过数据分析生产者消费者问题.
四、具体成果形式和要求
成果:生产者消费者问题程序语言实现;设计说明书。
要求:编写好的生产者消费者问题程序能够正确启动运行;设计说明书规范、合理。
进
度
安
排
起止日期
工作内容
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
//定义生产者线程
class ProducerThread implements Runnable {
int productNo = 0; //产品编号
int id; //生产者ID
public 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; //消费者ID
public 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缓冲区Buffer
class 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]。hasProduct+"\n");
}
}
}
/*
一个缓冲单元
*/
class ProductBuffer {
int product; //存放产品编号
boolean hasProduct; //标识该缓冲区是否有产品,true有产品,false无产品
}
3.1.7图形界面createUI
public 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来将生产者线程与消费者线程实例化.其实,在做这个实验之前我的Java语言编程老师讲过这些知识,正好可以巩固Java的一些知识。我还学过C++语言,这是大一下学期学的事了,我想要实现书上的P、V操作可以用C++语言来编写。 总之,通过该实验我更加清楚的认识到生产者与消费者这个经典问题实际上是线程同步问题的抽象描述,即计算机系统中的每个进程都可以消费(使用)或生产(释放)数据,进程释放数据相当于生产者,使用数据相当于消费者。
从Java 的多线程机制出发, 研究了操作系统中经典的同步问题-生产者消费者问题, 提出了两种解决此问题的模型, 及其Java 解决方案.提出的两个模型充分利用了Java 中面向对象和管程机制, 模拟了操作系统中进程同步的经典问题—生产者消费者问题。在第一个模型中, 我们按照生产者消费者问题典型的解决方案给出了Java 解决模型; 在第二个模型中, 我们分析了信号量mutex 在问题中所起的作用, 并为了提高缓冲区读写的效率, 提出了将信号量mutex 分为两个分别控制生产者和消费者的信号量,并讨论了此方案的可行性.
参考文献
[1] 《计算机操作系统》汤子瀛哲凤屏 汤小丹主编 西安电子科技大学出版社
[2] 《计算机操作系统概论》陈宏 杨忠耀主编 重庆邮电大学出版社
[3] 《计算机操作系统基本知识》廖成 崔阳 主编 电子工业出版社
[4] 《操作系统实现与设计》陆刚 望能主编 电子工业出版社
[5] 《java程序语言设计》丁振凡主编,薛清华副主编清华大学出版社
致谢
本组全体成员在此向所有关心我们的及帮助我们的老师和同学们致以最真诚的感谢。在本次毕业设计中,尤其要感谢杨传健老师,对我们的课程设计时刻的关注,当我们遇到困难时给了我们很大的帮助,交给了我们团队的合作理念,使得我们能够按时完成这次的课程设计.
学生签名: 填表日期: 年 月 日
附录
import java.awt.BorderLayout;
import java。awt。Color;
import java。awt.event.ActionEvent;
import java.awt。event.ActionListener;
import javax。swing。JButton;
import javax。swing.JFrame;
import javax.swing.JPanel;
import javax.swing。JScrollPane;
import javax。swing。JTextArea;
//import Producer_and_Customer.ConsumerThread;
//import Producer_and_Customer。ProducerThread;
/*
* 定义临界资源:缓冲队列
* */
class 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].hasProduct+”\n");
}
}
}
/*
一个缓冲单元
*/
class ProductBuffer {
int product; //存放产品编号
boolean hasProduct; //标识该缓冲区是否有产品,true有产品,false无产品
}
/*
* 生产者消费者问题实现(可以有多个生产者消费者)
* */
public class Producer_and_Customer implements ActionListener{
private JPanel jp[]=new JPanel[10];
boolean isRun = true; //用于控制线程结束
JTextArea ta = new JTextArea();
Buffer buffers = new Buffer(ta); //缓冲队列
static final int producerNum = 3; //生产者个数
static final int consumerNum = 3; //消费者个数
ProducerThread proThread[] = new ProducerThread[producerNum];
ConsumerThread conThread[] = new ConsumerThread[consumerNum];
Thread producer[] = new Thread[producerNum];
Thread consumer[] = new Thread[consumerNum];
public Producer_and_Customer(){
createUI();
//createNewUI();
//创建多个生产者和消费者线程并开始执行
for(int i=0; i〈producerNum; i++){
proThread[i] = new ProducerThread(i+1);
producer[i] = new Thread(proThread[i]);
producer[i].start();
}
for(int j=0; j〈consumerNum; j++){
conThread[j] = new ConsumerThread(j+1);
consumer[j] = new Thread(conThread[j]);
consumer[j].start();
}
}
private void createNewUI() {
JFrame frame=new JFrame(”Leo”);
}
//创建界面
public 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);
}
//按钮响应事件
public void actionPerformed(ActionEvent e){
isRun = false; //控制线程结束
System.out.println("停止”);
}
public static void main(String args[]){
Producer_and_Customer producerConsumer = new Producer_and_Customer();
}
//定义生产者线程
class ProducerThread implements Runnable {
int productNo = 0; //产品编号
int id; //生产者ID
public 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();
}
}
}
}
//定义消费者线程
class ConsumerThread implements Runnable {
int id; //消费者ID
public ConsumerThread(int id){
this。id = id;
}
public void run(){
while(isRun){
buffers。get(id); //从缓冲队列中取出产品
try{
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
指导教师评语
成绩评定
指导教师签名: 填表日期: 年 月 日
11
展开阅读全文