上机实验(老师的代码很好~)
一、 实验任务
问题描述:考虑有一些生产者和消费者进程,生产者进程生产信息并把它们放入缓冲池中,消费者从缓冲池中取走信息。生产者—消费者问题是相互合作的进程关系的一种抽象,如在输入时,输入进程是生产者,计算进程是消费者;而在输出时,则计算进程是生产者,打印进程是消费者。请使用信号量机制来解决生产者—消费者问题。
互斥关系:
(I)设缓冲池有n个单元。
(II)当n个单元装满时,生产者必须等待。
(III)当缓冲池空时,消费者必须等待。
二、实验目的
1. 加深对进程概念的理解,明确进程和程序的区别。
2. 进一步认识并发执行的实质。
3. 验证用信号量机制实现进程互斥的方法。
4. 验证用信号机制实现进程同步的方法。
三、实验环境
1. 一台运行Windows 7操作系统的计算机。
2. 选用以C、C++、visual c++、Java等任何一种语言。
四、实验要求
在程序编制中,应有数据显示,最好采用图形界面显示。
生产者和消费者的进程采用程序模拟的方法运行。
五、实验准备知识
1. 阅读课本有关进程管理以及进程同步的有关章节,对临界区和临界资源概念要清晰,充分理解信号信号量机制。
2. 阅读几种经典进程同步问题的算法并理解。熟练掌握生产者—消费者的算法思想。
Buffers类
import javax.swing.JTextArea; /** 定义临界资源:缓冲队列 * */ public class Buffers { JTextArea ta; static final int productBufferNum = 2; // 缓冲单元数 ProductBuffer pBuffer[] = new ProductBuffer[productBufferNum]; // 缓冲队列 int in = 0; // 缓冲单元指针,用于放产品 int out = 0; // 缓冲单元指针,用于取产品 int consumeProductNo; // 记录消费产品的编号 int usedBufferNum = 0; // 记录缓冲队列已使用的缓冲单元个数 public Buffers(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"); } } }
ProductBuffer类
/* 一个缓冲单元 */ public class ProductBuffer { int product; //存放产品编号 boolean hasProduct; //标识该缓冲区是否有产品,true有产品,false无产品 }
ProcuctConsumerMain类
import java.awt.BorderLayout; 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; /** 生产者消费者问题实现(可以有多个生产者消费者) **/ public class ProducerConsumerMain implements ActionListener { boolean isRun = true; //用于控制线程结束 JTextArea ta = new JTextArea(); Buffers buffers = new Buffers(ta); //缓冲队列 static final int producerNum = 8; //生产者个数 static final int consumerNum = 2; //消费者个数 ProducerThread proThread[] = new ProducerThread[producerNum]; ConsumerThread conThread[] = new ConsumerThread[consumerNum]; Thread producer[] = new Thread[producerNum]; Thread consumer[] = new Thread[consumerNum]; public ProducerConsumerMain() { createUI(); //创建界面 //创建多个生产者和消费者线程并开始执行 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(); } } //创建界面 public void createUI() { JFrame frame = new JFrame("生产者消费者"); JPanel panel = new JPanel(new BorderLayout()); JScrollPane scrPane = new JScrollPane(ta); panel.add(scrPane, BorderLayout.CENTER); JButton button = new JButton("停止"); button.addActionListener(this); panel.add(button, BorderLayout.SOUTH); 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[]) { ProducerConsumerMain producerConsumer = new ProducerConsumerMain(); } //定义生产者线程 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(100); } 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(100); } catch (Exception e) { e.printStackTrace(); } } } } }
运行界面