[关闭]
@Lxjeng 2016-05-13T10:00:08.000000Z 字数 5522 阅读 881

实验六 生产者消费者问题


  • 报告提交日期:2016.5.13 报告提交截止日期:2016.5.13
  • 姓名:梁晓静 学号:1405010530 班级:计算机5班

一、实验题目

  • 生产消费者问题

二、实验要求

  • 参考理发师问题,重新做一个具有GUI界面演示的生产者消费者问题的小软件,可用Java/QT相关编程来解决界面设计与实现问题!

三、实验平台

  • java编译平台eclipse

四、实验目的

  • 做一个具有GUI界面演示的生产者消费者问题的小软件。

五、实验流程

1、实验原理

  • 生产者和消费者线程通过Synchronized互斥锁对Stack共享资源进行访问,加了synchronized锁后,才能调用wait(),notify()和notifyAll()操作。生产者生产了一个apple“#"后调用push将apple“#”放到Stack中,如果Stack已满,生产者线程wait(),同时解锁,放开占有的资源,消费者对Stack操作,否则唤醒生产者并将apple“#”入栈;消费者也是同样的。本实验10个生产者,5个消费者。

2、运行结果

此处输入图片的描述

此处输入图片的描述
此处输入图片的描述

3、实验代码

  1. package lxjeng;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import javax.swing.*;
  5. public class PC extends WindowAdapter {// 主程序
  6. public PC() {
  7. JFrame f = new JFrame("生产者消费者图形界面模拟");
  8. JMenuBar menuBar = new JMenuBar();
  9. Content content = new Content();
  10. f.add("Center", content);
  11. Control control = new Control(content);
  12. f.add("North", control);
  13. f.setVisible(true);
  14. f.setSize(600, 570);
  15. Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
  16. Dimension frameSize = f.getSize();
  17. f.setLocation((screenSize.width - frameSize.width) / 2, (screenSize.height - frameSize.height) / 2);// 设置主界面显示位置
  18. f.addWindowListener(this);
  19. f.setJMenuBar(menuBar);
  20. /* menuHelp.add(menuHelpAbout);
  21. menuBar.add(menuHelp);*/
  22. }
  23. void fileExit_ActionPerformed(ActionEvent e) {
  24. System.exit(0);
  25. }
  26. public void windowClosing(WindowEvent arg0) {
  27. System.exit(0);
  28. }
  29. public static void main(String args[]) {
  30. new PC();
  31. }
  32. }
  33. class Content extends JPanel {// content是主显示部分
  34. JTextField tf1, tf2, tf3, tf4, tf5, tf6;
  35. JTextArea ta;
  36. public Content() {
  37. setLayout(null);
  38. tf1 = new JTextField();// 六个JTextField模仿堆栈
  39. tf2 = new JTextField();
  40. tf3 = new JTextField();
  41. tf4 = new JTextField();
  42. tf5 = new JTextField();
  43. tf6 = new JTextField();
  44. add(tf1);
  45. add(tf2);
  46. add(tf3);
  47. add(tf4);
  48. add(tf5);
  49. add(tf6);
  50. int a = 94;
  51. int b = 100;
  52. int c = 197, d = 45;
  53. tf1.setBounds(new Rectangle(b, a + 225, c, d));// JTextField的显示位置
  54. tf2.setBounds(new Rectangle(b, a + 180, c, d));
  55. tf3.setBounds(new Rectangle(b, a + 135, c, d));
  56. tf4.setBounds(new Rectangle(b, a + 90, c, d));
  57. tf5.setBounds(new Rectangle(b, a + 45, c, d));
  58. tf6.setBounds(new Rectangle(b, a, c, d));
  59. tf1.setHorizontalAlignment(JTextField.CENTER); // JTextField中的内容居中显示
  60. tf2.setHorizontalAlignment(JTextField.CENTER);
  61. tf3.setHorizontalAlignment(JTextField.CENTER);
  62. tf4.setHorizontalAlignment(JTextField.CENTER);
  63. tf5.setHorizontalAlignment(JTextField.CENTER);
  64. tf6.setHorizontalAlignment(JTextField.CENTER);
  65. ta = new JTextArea();
  66. JScrollPane sp = new JScrollPane(ta);
  67. add(sp);
  68. sp.setBounds(new Rectangle(380, 50, 170, 370));
  69. ta.setLineWrap(true);
  70. }
  71. int z = 0;
  72. public void showPush(char c, int index) {// 入栈的界面显示控制
  73. switch (index) {
  74. case 1:
  75. tf1.setText("" + c + "");
  76. break;
  77. case 2:
  78. tf2.setText("" + c + "");
  79. break;
  80. case 3:
  81. tf3.setText("" + c + "");
  82. break;
  83. case 4:
  84. tf4.setText("" + c + "");
  85. break;
  86. case 5:
  87. tf5.setText("" + c + "");
  88. break;
  89. case 6:
  90. tf6.setText("" + c + "");
  91. }
  92. ta.insert(Thread.currentThread().getName() + "生产:" + "apple" + c + "\n", z);
  93. }
  94. public void showPop(char c, int index) {// 出栈的界面显示控制
  95. switch (index) {
  96. case 1:
  97. tf1.setText("");
  98. break;
  99. case 2:
  100. tf2.setText("");
  101. break;
  102. case 3:
  103. tf3.setText("");
  104. break;
  105. case 4:
  106. tf4.setText("");
  107. break;
  108. case 5:
  109. tf5.setText("");
  110. break;
  111. case 6:
  112. tf6.setText("");
  113. }
  114. ta.insert(Thread.currentThread().getName() + "消费:" + "apple" + c + "\n", z);
  115. }
  116. public void clear() {// 清空JTextArea来进行“重新开始”
  117. ta.setText("");
  118. }
  119. public void full() {
  120. ta.insert("栈满,生产者wait\n", z);
  121. }
  122. public void empty() {
  123. ta.insert("栈空,消费者wait\n", z);
  124. }
  125. }
  126. class Control extends JPanel implements ActionListener {
  127. JButton start = new JButton("开始");
  128. Content content;
  129. public Control(Content content) {
  130. this.content = content;
  131. add(start);
  132. start.addActionListener(this);
  133. }
  134. public void actionPerformed(ActionEvent e) {
  135. go();
  136. }
  137. public void go() {
  138. SyncStack stack = new SyncStack(content);
  139. Runnable producer1 = new Producer(stack);
  140. Runnable producer2 = new Producer(stack);
  141. Runnable producer3 = new Producer(stack);
  142. Runnable producer4 = new Producer(stack);
  143. Runnable consumer1 = new Consumer(stack);
  144. Runnable consumer2 = new Consumer(stack);
  145. Runnable consumer3 = new Consumer(stack);
  146. Runnable consumer4 = new Consumer(stack);
  147. Thread p1 = new Thread(producer1, "生产者1");
  148. Thread p2 = new Thread(producer2, "生产者2");
  149. Thread p3 = new Thread(producer3, "生产者3");
  150. Thread p4 = new Thread(producer4, "生产者4");
  151. Thread p5 = new Thread(producer4, "生产者5");
  152. Thread p6 = new Thread(producer4, "生产者6");
  153. Thread p7 = new Thread(producer4, "生产者7");
  154. Thread p8 = new Thread(producer4, "生产者8");
  155. Thread p9 = new Thread(producer4, "生产者9");
  156. Thread p10 = new Thread(producer4, "生产者10");
  157. Thread c1 = new Thread(consumer1, "消费者1");
  158. Thread c2 = new Thread(consumer2, "消费者2");
  159. Thread c3 = new Thread(consumer2, "消费者3");
  160. Thread c4 = new Thread(consumer2, "消费者4");
  161. Thread c5 = new Thread(consumer2, "消费者5");
  162. p1.start();
  163. p2.start();
  164. p3.start();
  165. p4.start();
  166. p5.start();
  167. p6.start();
  168. p7.start();
  169. p8.start();
  170. p9.start();
  171. p10.start();
  172. c1.start();
  173. c2.start();
  174. c3.start();
  175. c4.start();
  176. c5.start();
  177. }
  178. }
  179. class SyncStack// 共享资源
  180. {
  181. Content theCon;
  182. public SyncStack(Content c) {
  183. theCon = c;
  184. }
  185. private int index = 0;// 堆栈指针初始值为0
  186. private char[] buffer = new char[6];// 堆栈有6个字符的空间
  187. public synchronized void push(char c)// 加上互斥锁
  188. {
  189. while (index == buffer.length)// 堆栈已满,不能压栈
  190. {
  191. try {
  192. this.wait();// 等待,直到有数据出栈
  193. theCon.full();
  194. } catch (InterruptedException e) {
  195. }
  196. }
  197. this.notify();
  198. buffer[index] = c;
  199. index++;
  200. theCon.showPush(c, index);
  201. }
  202. public synchronized char pop()
  203. {
  204. while (index == 0)
  205. {
  206. try {
  207. this.wait();
  208. theCon.empty();
  209. } catch (InterruptedException e) {
  210. }
  211. }
  212. this.notify();
  213. char c = buffer[index - 1];
  214. theCon.showPop(c, index);
  215. index--;
  216. return buffer[index];
  217. }
  218. }
  219. class Producer implements Runnable
  220. {
  221. SyncStack theStack;
  222. public Producer(SyncStack s) {
  223. theStack = s;
  224. }
  225. public void run() {
  226. char c;
  227. for (int i = 0; i < 20; i++) {
  228. c = '#';
  229. theStack.push(c);
  230. try {
  231. Thread.sleep((int) (Math.random() * 4000));// 每产生一个字母后线程就随即睡眠一段时间
  232. } catch (InterruptedException e) {
  233. }
  234. }
  235. }
  236. }
  237. class Consumer implements Runnable
  238. {
  239. SyncStack theStack;
  240. public Consumer(SyncStack s) {
  241. theStack = s;
  242. }
  243. public void run() {
  244. char c;
  245. for (int i = 0; i < 20; i++) {
  246. c = theStack.pop();
  247. try {
  248. Thread.sleep((int) (Math.random() * 6000));
  249. } catch (InterruptedException e) {
  250. }
  251. }
  252. }
  253. }

六、实验体会

  • 本次实验对我来说有一定难度,在参考老师给的理发师问题相关资料和同学做好的实验后,理解了他程序的大概意思,然而自己还是不能独立完成,所以借鉴了其源程序加以理解和稍稍修改。这次实验的关键在于同步方法和锁的机制,也让我见识到了Java对多线程的支持与同步机制的强大。
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注