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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 孙百鑫 高级黑马   /  2013-4-21 11:03  /  1083 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 孙百鑫 于 2013-4-21 15:42 编辑
  1. class ProduceConsume
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Res r=new Res();
  6.                 new Thread(new Produce(r)).start();
  7.                 new Thread(new Consume(r)).start();
  8.                 new Thread(new Produce(r)).start();
  9.                 new Thread(new Consume(r)).start();
  10.                 new Thread(new Produce(r)).start();
  11.                 new Thread(new Consume(r)).start();
  12.                 new Thread(new Produce(r)).start();
  13.                 new Thread(new Consume(r)).start();
  14.                 new Thread(new Produce(r)).start();
  15.                 new Thread(new Consume(r)).start();
  16.                 new Thread(new Produce(r)).start();
  17.                 new Thread(new Consume(r)).start();
  18.                 //问题是.开启这么多线程就出问题了.打印结果.求解决因为什么??????????????
  19.                 /*
  20.                 Thread-0生产商品..244
  21.                 Thread-7消费.........商品..244
  22.                 Thread-6生产商品..245
  23.                 Thread-1消费.........商品..245
  24.                 Thread-5消费.........商品..245
  25.                 Thread-4生产商品..246
  26.                 Thread-5消费.........商品..246
  27.                 Thread-1消费.........商品..246
  28.                 Thread-6生产商品..247
  29.                 Thread-7消费.........商品..247
  30.                 Thread-0生产商品..248
  31.                 Thread-8生产商品..249
  32.                 Thread-9消费.........商品..249
  33.                 Thread-3消费.........商品..249
  34.                 */
  35.         
  36.         }
  37. }
  38. class Res
  39. {
  40.         private String name;
  41.         private int count;//计数
  42.         private boolean flag;//用于判断if是否该执行

  43.         public synchronized void set(String name)//存入线程
  44.         {
  45.                 if(flag)//如果是假等待
  46.                         try
  47.                         {
  48.                                 this.wait();
  49.                         }
  50.                         catch (Exception e)
  51.                         {
  52.                         }
  53.                 this.name=name+".."+count++;//如果是真.赋值并计数打印
  54.                 System.out.println(Thread.currentThread().getName()+"生产"+this.name);
  55.                 flag=true;//然后变成真.并把全部线程唤醒
  56.                 this.notifyAll();               
  57.         }
  58.         public synchronized void out()//打印线程
  59.         {
  60.                 if(!flag)//如果非假开始等待
  61.                         try
  62.                         {
  63.                                 this.wait();
  64.                         }
  65.                         catch (Exception e)
  66.                         {
  67.                         }
  68.                         //否则就打印.并且改为假.并把全部线程唤醒
  69.                 System.out.println(Thread.currentThread().getName()+"消费........."+this.name);
  70.                 flag=false;
  71.                 this.notifyAll();
  72.         }
  73. }

  74. class Produce implements Runnable//存入线程
  75. {
  76.         private Res r;//建立对象引用
  77.         Produce(Res r)
  78.         {
  79.                 this.r=r;//初始化对象
  80.         }
  81.         public void run()
  82.         {
  83.                 while(true)//往里存商品.
  84.                 {                        
  85.                         r.set("商品");        
  86.                 }
  87.                         
  88.         }
  89. }
  90. class Consume implements Runnable//打印线程
  91. {
  92.         private Res r;//建立对象引用
  93.         Consume(Res r)
  94.         {
  95.                 this.r=r;
  96.         }
  97.         public void run()
  98.         {
  99.                 while(true)//打印商品
  100.                         r.out();
  101.         }
  102. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

2 个回复

倒序浏览
这个视频上有讲的;
代码完成,加入同步和等待唤醒机制后,可以实现,生产一个,就消费一个。
        可是在实际开发中,生产者和消费者,不是一个。有可能是多个
        也就是有多个生产者生产,有多个消费者消费。
        造成数据错误的原因:当生产者消费者多个时,
        本方的线程有可能唤醒本方的线程,而且,本方被唤醒后,没有判断标记,就进行了执行,
        会到导致原来本方的操作还没有被对方所操作就已经被覆盖了。
        生产者1,进行了生产后,将本方生产者2唤醒,生产者2没有判断标记直接继续生产,
        导致生产者1的产品还没有被消费就覆盖了。
解决方式:因为有本方唤醒本方的情况,所以必须每次的醒来都要判断一次标记。
        判断标记的动作要执行多次。所以不使用if,而是使用while.
  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)                                        //加上while判断标记
  9.                         try{this.wait();}catch(Exception e){}        //等待
  10.                 this.name=name+"----"+count++;
  11.                
  12.                 System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
  13.                 flag=true;
  14.                 this.notifyAll();//唤醒全部
  15.         }

  16.         public synchronized void out()
  17.         {
  18.                 while(!flag)
  19.                         try{this.wait();}catch(Exception e){}
  20.                 System.out.println(Thread.currentThread().getName()+"......消费者......"+this.name);
  21.                 flag=false;
  22.                 this.notifyAll();
  23.         }
  24. }
  25. class Producer implements Runnable
  26. {
  27.         private Resource res;
  28.         Producer(Resource res)
  29.         {
  30.                 this.res=res;
  31.         }
  32.         public void run()
  33.         {
  34.                 while(true)
  35.                 {
  36.                         res.set("==商品==");
  37.                 }
  38.         }
  39. }
  40. class Consumer implements Runnable
  41. {
  42.         private Resource res;
  43.         Consumer(Resource res)
  44.         {
  45.                 this.res=res;
  46.         }
  47.         public void run()
  48.         {
  49.                 while(true)
  50.                 {
  51.                         res.out();
  52.                 }
  53.         }
  54. }
  55. class Demo2
  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 t1 = new Thread(pro);       
  63.                 Thread t2 = new Thread(pro);       
  64.                 Thread t3 = new Thread(con);
  65.                 Thread t4 = new Thread(con);

  66.                 t1.start();
  67.                 t2.start();                                               
  68.                 t3.start();
  69.                 t4.start();
  70.         }
  71. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄玉昆 + 1

查看全部评分

回复 使用道具 举报
up.yfei 发表于 2013-4-21 11:13
这个视频上有讲的;
代码完成,加入同步和等待唤醒机制后,可以实现,生产一个,就消费一个。
        可是在实际 ...

哦买噶.!!!!!谢谢了.居然犯了这么简单的错误......while....和if写错了.....
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马