A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© ying 中级黑马   /  2013-1-7 20:22  /  1633 人查看  /  5 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 ying 于 2013-1-8 13:12 编辑
  1. /*
  2. 线程模拟生产者与消费者
  3. 要求:生产一个消费一个
  4. */
  5. class ProducterConsumerDemo
  6. {
  7. public static void main(String[] args)
  8. {
  9. Resource r = new Resource(); //定义商品资源
  10. Producter pro = new Producter(r);//创建生产者对象
  11. Consumer son = new Consumer(r); //创建消费者对象

  12. //创建两个生产者即两个线程
  13. Thread t1 = new Thread(pro);
  14. Thread t2 = new Thread(pro);

  15. //创建两个消费者即两个线程
  16. Thread t3 = new Thread(son);
  17. Thread t4 = new Thread(son);

  18. //启动四个线程并执行相应的run方法
  19. t1.start();
  20. t2.start();
  21. t3.start();
  22. t4.start();


  23. }
  24. }
  25. /*
  26. 定义商品类
  27. */
  28. class Resource
  29. {
  30. private String name; //商品的名字
  31. private int count =1; //商品的编号
  32. private boolean flag = false;

  33. public synchronized void set(String name)
  34. {
  35. if(flag)
  36. try{this.wait();}catch(Exception e){}
  37. this.name = name + "--" + count++;//
  38. System.out.println(Thread.currentThread().getName() + "...生产者 " + this.name);
  39. flag = true;
  40. this.notify();
  41. }
  42. public synchronized void out()
  43. {
  44. if(!flag)
  45. try{this.wait();}catch(Exception e){}
  46. System.out.println(Thread.currentThread().getName() + "...消费者————" + this.name);
  47. flag = false;
  48. this.notify();
  49. }
  50. }
  51. // 商品的生产者
  52. class Producter implements Runnable
  53. {
  54. private Resource res;

  55. Producter(Resource res)
  56. {
  57. this.res = res;
  58. }
  59. public void run()
  60. {
  61. while(true)
  62. {
  63. res.set("商品+");
  64. }
  65. }
  66. }
  67. //商品的消费者
  68. class Consumer implements Runnable
  69. {
  70. private Resource res;

  71. Consumer(Resource res)
  72. {
  73. this.res = res;
  74. }
  75. public void run()
  76. {
  77. while(true)
  78. {
  79. res.out();
  80. }
  81. }
  82. }
复制代码
我的代码的生产者和消费者不和谐了,有时候生产一个会消费两个或者生产两个消费一个!我弄了半天也没弄懂到底是错在哪里了!请高手指教!!

ConsuProduc.jpg (87.65 KB, 下载次数: 56)

ConsuProduc.jpg

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1 神马都是浮云

查看全部评分

5 个回复

倒序浏览
将if换成while循环  代码中的this.notify(); 改成notifyAll();
回复 使用道具 举报
  1. package demo1;

  2. /*
  3. 线程模拟生产者与消费者
  4. 要求:生产一个消费一个
  5. */
  6. class ProducterConsumerDemo {
  7.         public static void main(String[] args) {
  8.                 Resource r = new Resource(); // 定义商品资源
  9.                 Producter pro = new Producter(r);// 创建生产者对象
  10.                 Consumer son = new Consumer(r); // 创建消费者对象

  11.                 // 创建两个生产者即两个线程
  12.                 Thread t1 = new Thread(pro);
  13.                 Thread t2 = new Thread(pro);

  14.                 // 创建两个消费者即两个线程
  15.                 Thread t3 = new Thread(son);
  16.                 Thread t4 = new Thread(son);

  17.                 // 启动四个线程并执行相应的run方法
  18.                 t1.start();
  19.                 t2.start();
  20.                 t3.start();
  21.                 t4.start();

  22.         }
  23. }

  24. /*
  25. * 定义商品类
  26. */
  27. class Resource {
  28.         private String name; // 商品的名字
  29.         private int count = 1; // 商品的编号
  30.         private boolean flag = false;

  31.         public synchronized void set(String name) {
  32.                 while (flag)
  33.                         try {
  34.                                 this.wait();
  35.                         } catch (Exception e) {
  36.                         }
  37.                 this.name = name + "--" + count++;//
  38.                 System.out.println(Thread.currentThread().getName() + "...生产者 "
  39.                                 + this.name);
  40.                 flag = true;
  41.                 this.notifyAll();
  42.         }

  43.         public synchronized void out() {
  44.                 while (!flag)
  45.                         try {
  46.                                 this.wait();
  47.                         } catch (Exception e) {
  48.                         }
  49.                 System.out.println(Thread.currentThread().getName() + "...消费者————"
  50.                                 + this.name);
  51.                 flag = false;
  52.                 this.notifyAll();
  53.         }
  54. }

  55. // 商品的生产者
  56. class Producter implements Runnable {
  57.         private Resource res;

  58.         Producter(Resource res) {
  59.                 this.res = res;
  60.         }

  61.         public void run() {
  62.                 while (true) {
  63.                         res.set("商品+");
  64.                 }
  65.         }
  66. }

  67. // 商品的消费者
  68. class Consumer implements Runnable {
  69.         private Resource res;

  70.         Consumer(Resource res) {
  71.                 this.res = res;
  72.         }

  73.         public void run() {
  74.                 while (true) {
  75.                         res.out();
  76.                 }
  77.         }
  78. }
复制代码
我把你的代码改了一下,运行正常,你的错误主要有两个,
第一:判断是用while,而不是if,因为多个线程可能在if的下面,当线程醒来时,根本就有再进行判断,而此时由于一个线程的消费而使务件不成立了,但是由于线程都在if下面,所以根本不需要再次判断就直接再次消费而引起的。
第二:你必须唤醒全部的线程,要不然因为线程的唤醒是随机的,不确定的,当消费了之的,再次唤醒的双是在等待当中的消费线程时,就出出了多消费的情况。如果你使用了多次循还判断,那么必须唤醒的全部线程,然不然可能出现死锁的情况。因为有可能全部的线程都处于等待唤醒的状态。

评分

参与人数 1技术分 +1 收起 理由
冯海霞 + 1

查看全部评分

回复 使用道具 举报
类似需要有加锁的操作。我也记得不是很清楚,但是毕老师在多线程视频中好像讲的很清楚,建议你看一下!!好像是用等待唤醒机制!
回复 使用道具 举报
嗯!谢谢各位!问题解决了!

点评

最好是在问题解决后将帖子改为已解决,谢谢!  发表于 2013-1-8 12:08
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马