上機實驗(老師的代碼很好~)
一、 實驗任務
問題描述:考慮有一些生產者和消費者進程,生產者進程生產信息並把它們放入緩沖池中,消費者從緩沖池中取走信息。生產者—消費者問題是相互合作的進程關系的一種抽象,如在輸入時,輸入進程是生產者,計算進程是消費者;而在輸出時,則計算進程是生產者,打印進程是消費者。請使用信號量機制來解決生產者—消費者問題。
互斥關系:
(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(); } } } } }
運行界面

