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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© haozi050 中级黑马   /  2014-2-1 00:28  /  1250 人查看  /  2 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 haozi050 于 2014-2-9 08:33 编辑

有一个很奇怪的问题,我照着视频写了生产者消费者代码,运行出结果了,但商品标记count没有一次是从1开始的.我运行了别人的正确代码也不是从1开始打印的,哪位大神能告诉我为什么吗?Thread-2..消费者..馒头50090
Thread-1..生产者..馒头50091
Thread-3..消费者..馒头50091
Thread-0..生产者..馒头50092
Thread-2..消费者..馒头50092
Thread-1..生产者..馒头50093
Thread-3..消费者..馒头50093
Thread-0..生产者..馒头50094
Thread-2..消费者..馒头50094
Thread-1..生产者..馒头50095
Thread-3..消费者..馒头50095
Thread-0..生产者..馒头50096
Thread-2..消费者..馒头50096
一开始就是50090,下面是代码:

  1. import java.util.concurrent.locks.*;
  2. //定义资源类
  3. class OneResource
  4. {
  5.         private String name;//名称
  6.         private int count=1;//编号
  7.         boolean flag=false;//标记
  8. //        创建一个锁对象
  9.         Lock lock=new ReentrantLock();
  10. //        创建两个监视器方法对象,一个监视生产者,一个监视消费者
  11.         Condition produce=lock.newCondition();
  12.         Condition consume=lock.newCondition();
  13.         public void set(String name)//定义生产馒头方法
  14.         {
  15. //                上锁
  16.                 lock.lock();
  17. //                如果标记为假就进行生产否则就等待。由于会抛异常,防止异常之后没释放锁,要用try finally
  18.                 try{
  19.                         while(flag)
  20.                         {try{produce.await();}catch(InterruptedException e){}}
  21.                         this.name=name+count;
  22.                         System.out.println(Thread.currentThread().getName()+"..生产者.."+this.name);
  23.                         count++;
  24.         //                生产完之后将标记改为真,唤醒消费者线程。
  25.                         flag=true;
  26.                         consume.signal();
  27.                 }
  28. //                释放锁
  29.                 finally{
  30.                         lock.unlock();
  31.                 }
  32.         }
  33.         public void get()//定义消费方法
  34.         {
  35.                 lock.lock();
  36.                 try{
  37.         //                如果标记为真则消费,否则等待
  38.                         while(!flag)
  39.                         {
  40.                                 {try{consume.await();}catch(InterruptedException e){}}
  41.                         }
  42.                         System.out.println(Thread.currentThread().getName()+"..消费者.."+this.name);
  43.         //                 消费完之后将标记改为假,唤醒生产者
  44.                         flag=false;
  45.                         produce.signal();
  46.                 }finally{
  47.                         lock.unlock();
  48.                 }
  49.          }
  50. }
  51. //定义生产者
  52. class MoreProducer implements Runnable
  53. {
  54. //        为了保证资源一致,这里定义构造函数接受资源对象,一初始化时就有资源对象。
  55.         OneResource r;
  56.         MoreProducer(OneResource r)
  57.         {
  58.                 this.r=r;
  59.         }
  60. //        明确生产者的任务,生产馒头
  61.         public void run()
  62.         {
  63. //                一直生产
  64.                 while(true)
  65.                 r.set("馒头");
  66.         }
  67. }
  68. //定义消费者类
  69. class MoreConsumer implements  Runnable
  70. {
  71. //        一初始化也要有统一的资源对象
  72.         OneResource r;
  73.         MoreConsumer(OneResource r)
  74.         {
  75.                 this.r=r;
  76.         }
  77. //        明确消费者的消费任务
  78.         public void run()
  79.         {
  80. //                一直消费
  81.                 while(true)
  82.                         r.get();
  83.         }
  84. }
  85. public class ProducerConsumerFinal {

  86.         public static void main(String[] args) {
  87. //创建资源对象,并将资源传递给生产者消费者
  88. //                创建任务对象即生产任务和消费任务,生产任务和消费任务都只有一个
  89.                 OneResource  r=new OneResource();
  90.                 MoreProducer p1=new MoreProducer(r);
  91.                 MoreConsumer c1=new MoreConsumer(r);
  92. //                创建线程并指定线程任务
  93.                 Thread t0=new Thread(p1);
  94.                 Thread t1=new Thread(p1);
  95.                 Thread t2=new Thread(c1);
  96.                 Thread t3=new Thread(c1);
  97.                 t0.start();
  98.                 t1.start();
  99.                 t2.start();
  100.                 t3.start();
  101.                
  102.         }

  103. }
复制代码




2 个回复

倒序浏览
另一个贴里已经说了~
运行太快,记录太多把前面的覆盖了。
eclipse里可以通过:右键--run as--run configurations--里的common标签配置将结果输出到文件就可以看到了。
命令行可以通过 java ProducerConsumerFinal >>log.txt将结果输出到当前工作目录的log.txt文件。以方便查看。

另建议运行后立马停止。不然记录太多打开会很卡
回复 使用道具 举报
e.c 发表于 2014-2-4 16:10
另一个贴里已经说了~
运行太快,记录太多把前面的覆盖了。
eclipse里可以通过:右键--run as--run configur ...

或者让生产消费后线程sleep(500)休眼一会儿就可以看到了
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马