黑马程序员技术交流社区

标题: 关于两个生产者两个消费者的运行结果——求解释 [打印本页]

作者: dicegame    时间: 2013-7-28 19:10
标题: 关于两个生产者两个消费者的运行结果——求解释
本帖最后由 杜光 于 2013-8-4 10:06 编辑
  1. package qbb;

  2. class Resource {
  3.         private String name;
  4.         private int no = 1;
  5.         private boolean flag = false;
  6.         public synchronized void produce(String name) {
  7.                 if(flag) {
  8.                         try {
  9.                                 wait();
  10.                         } catch (InterruptedException e) {
  11.                                 e.printStackTrace();
  12.                         }
  13.                 }
  14.                 this.name = name + "---" + no++;
  15.                 System.out.println(Thread.currentThread().getName() +
  16.                                 "---生产者: " + this.name);
  17.                 flag = true;
  18.                 notify();
  19.         }
  20.         public synchronized void consume() {
  21.                 if(!flag) {
  22.                         try {
  23.                                 wait();
  24.                         } catch (InterruptedException e) {
  25.                                 e.printStackTrace();
  26.                         }
  27.                 }
  28.                 System.out.println(Thread.currentThread().getName() +
  29.                                 "---消费者----: " + name);
  30.                 flag = false;
  31.                 notify();
  32.         }
  33. }
  34. class Producer implements Runnable {
  35.         private Resource r;
  36.         Producer(Resource r) {
  37.                 this.r = r;
  38.         }
  39.         public void run() {
  40.                 while(true) {
  41.                         r.produce("商品");
  42.                 }
  43.         }
  44. }
  45. class Consumer implements Runnable {
  46.         private Resource r;
  47.         Consumer(Resource r) {
  48.                 this.r = r;
  49.         }
  50.         public void run() {
  51.                 while(true) {
  52.                         r.consume();
  53.                 }
  54.         }
  55. }
  56. public class ProducerConsumer {
  57.         public static void main(String[] args) {
  58.                 Resource res = new Resource();
  59.                 Producer pro = new Producer(res);
  60.                 Consumer con = new Consumer(res);
  61.                 Thread t1 = new Thread(pro);
  62.                 Thread t2 = new Thread(pro);
  63.                 Thread t3 = new Thread(con);
  64.                 Thread t4 = new Thread(con);
  65.                 t1.start();
  66.                 t2.start();
  67.                 t3.start();
  68.                 t4.start();
  69.         }
  70. }
复制代码
运行结果会出现以下片段:
Thread-2---消费者----: 商品---477219
Thread-3---消费者----: 商品---477219
Thread-2---消费者----: 商品---477219
Thread-3---消费者----: 商品---477219
Thread-2---消费者----: 商品---477219
怎么解释呢?线程间怎么切换才能出现这种结果呢?


作者: 黑马李昂    时间: 2013-8-3 23:32
  1. public synchronized void produce(String name) {

  2. if(flag) {//问题出现在这里:if判断标记,只有一次,会导致不该运行的线程运行了。出现了数据错误的情况。while判断标记,解决了线程获取执行权后,是否要运行!

  3. try {

  4. wait();

  5. } catch (InterruptedException e) {

  6. e.printStackTrace();

  7. }

  8. }

  9. this.name = name + "---" + no++;

  10. System.out.println(Thread.currentThread().getName() +

  11. "---生产者: " + this.name);

  12. flag = true;

  13. notify();//同时这里改成notifyAll();不然出现死锁情况

  14. }

复制代码
与楼主共同学习{:soso_e100:}

完整代码如下
  1. class Resource
  2. {
  3. private String name;
  4. private int count = 1;
  5. private boolean flag = false;
  6. public synchronized void set(String name)
  7. {
  8. while(flag)
  9. try{this.wait();}catch(InterruptedException e){}

  10. this.name = name + count;
  11. count++;
  12. System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
  13. flag = true;
  14. notifyAll();
  15. }

  16. public synchronized void out()// t3
  17. {
  18. while(!flag)
  19. try{this.wait();}catch(InterruptedException e){}
  20. System.out.println(Thread.currentThread().getName()+"...消费者........"+this.name);
  21. flag = false;
  22. notifyAll();
  23. }
  24. }

  25. class Producer implements Runnable
  26. {
  27. private Resource r;
  28. Producer(Resource r)
  29. {
  30. this.r = r;
  31. }
  32. public void run()
  33. {
  34. while(true)
  35. {
  36. r.set("商品");
  37. }
  38. }
  39. }

  40. class Consumer implements Runnable
  41. {
  42. private Resource r;
  43. Consumer(Resource r)
  44. {
  45. this.r = r;
  46. }
  47. public void run()
  48. {
  49. while(true)
  50. {
  51. r.out();
  52. }
  53. }
  54. }



  55. class ProducerConsumerDemo
  56. {
  57. public static void main(String[] args)
  58. {
  59. Resource r = new Resource();
  60. Producer pro = new Producer(r);
  61. Consumer con = new Consumer(r);

  62. Thread t0 = new Thread(pro);
  63. Thread t1 = new Thread(pro);
  64. Thread t2 = new Thread(con);
  65. Thread t3 = new Thread(con);
  66. t0.start();
  67. t1.start();
  68. t2.start();
  69. t3.start();

  70. }
复制代码

作者: dicegame    时间: 2013-8-3 23:36
黑马李昂 发表于 2013-8-3 23:32
与楼主共同学习

完整代码如下

哥们,谢谢
不过,我知道正确的代码怎么写
我就是想知道再不同步的情况下
四个线程间怎么切换才能出现上面的结果
想把这个过程搞清楚
有点找虐的意思:lol
作者: 黑马李昂    时间: 2013-8-3 23:45
线程这个东西是动态的,这个真想画图给你解释,又怕画的不明白,毕向东java基础视频第14天第26个视频有详细介绍{:soso_e112:}可以回顾回顾




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2