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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 草貌路飞 高级黑马   /  2013-7-8 18:04  /  1286 人查看  /  4 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 草貌路飞 于 2013-7-9 10:37 编辑

本来是要照着毕老师的代码写的,可以记错了,把应该在生产线程中的while(true)放到生产方法中去了。导致出现问题IllegalMonitorStateException,虽然知道问题所在了,但不明白这个问题是怎么产生的。哪位同学帮忙解释下问题产生的流程。
  1. import java.util.concurrent.locks.Condition;
  2. import java.util.concurrent.locks.ReentrantLock;

  3. public class NewThreadDemo
  4. {
  5.         public static void main(String[] args)
  6.         {
  7.                 Product p = new Product();
  8.                 new Thread(new ProThread(p)).start();
  9.                 new Thread(new ConsThread(p)).start();
  10.         }
  11. }
  12. class Product
  13. {
  14.         private int proNum = 0;
  15.         private boolean hasProduct = false;
  16.         
  17.         private ReentrantLock lock = new ReentrantLock();
  18.         private Condition condition = lock.newCondition();
  19.         public void produce()
  20.         {
  21.                 lock.lock();
  22.                 while(true)//这里写错了,while(true)应该放在run里面的。
  23.                 {
  24.                         try
  25.                         {
  26.                                 while(hasProduct)
  27.                                 {
  28.                                         System.out.println(Thread.currentThread().getName() + ":::::::wait");
  29.                                         condition.await();
  30.                                 }
  31.                                 System.out.println(Thread.currentThread().getName() + ":produce:" +  ++proNum);
  32.                                 hasProduct = true;
  33.                                 condition.signal();
  34.                         }
  35.                         catch(Exception e)
  36.                         {
  37.                                 e.printStackTrace();
  38.                         }
  39.                         finally
  40.                         {
  41.                                 lock.unlock();
  42.                         }
  43.                 }
  44.         }
  45.         public void consume()
  46.         {
  47.                 lock.lock();
  48.                 try
  49.                 {
  50.                         while(!hasProduct)
  51.                         {
  52.                                 System.out.println(Thread.currentThread().getName() + ":::::::wait");
  53.                                 try{condition.await();}catch(Exception e){e.printStackTrace();}
  54.                         }
  55.                         System.out.println(Thread.currentThread().getName() + "::consume::" + proNum);
  56.                         hasProduct = false;
  57.                         condition.signal();
  58.                 }
  59.                 catch(Exception e)
  60.                 {
  61.                         e.printStackTrace();
  62.                 }
  63.                 finally
  64.                 {
  65.                         lock.unlock();
  66.                 }
  67.         }
  68. }

  69. class ProThread implements Runnable
  70. {
  71.         private Product product;
  72.         
  73.         ProThread(Product product)
  74.         {
  75.                 this.product = product;
  76.         }
  77.         
  78.         public void run()
  79.         {
  80.                 product.produce();
  81.         }
  82. }
  83. class ConsThread implements Runnable
  84. {
  85.         private Product product;
  86.         
  87.         ConsThread(Product product)
  88.         {
  89.                 this.product = product;
  90.         }
  91.         public void run()
  92.         {
  93.                 while(true)
  94.                         product.consume();
  95.         }
  96. }
复制代码

1.jpg (23.13 KB, 下载次数: 0)

这是执行结果,每次结果都是一样的

这是执行结果,每次结果都是一样的

评分

参与人数 1技术分 +1 收起 理由
杨兴庭 + 1

查看全部评分

4 个回复

倒序浏览
27行的while换成if试试
回复 使用道具 举报
张承富 发表于 2013-7-9 01:48
27行的while换成if试试

不能换的,那里格式就得这样,否则在那里等待的线程被唤醒后如果不重新判断会出问题,如唤醒的是和自己做一样事的线程
回复 使用道具 举报
liukunaitasa 发表于 2013-7-9 09:03
问题还是在你写错的那个生产方法里。
由于你在生产方法里把 while(true)写在了lock.lock()下面。
因此,生 ...

嗯..明白了,生产完一个后它就把锁扔了,当它要wait的时候因为没有这个锁,wati就出错了
回复 使用道具 举报
liukunaitasa 发表于 2013-7-9 09:03
问题还是在你写错的那个生产方法里。
由于你在生产方法里把 while(true)写在了lock.lock()下面。
因此,生 ...

正解,无限循环之中没有锁语句,消费者执行完毕,唤醒生产者,但生产者并没有尝试去竞争锁,在没有锁的代码块中执行condition.await(),会报异常的
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马