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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 晓天s 中级黑马   /  2013-9-16 22:02  /  1539 人查看  /  6 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 杨增坤 于 2013-9-17 20:02 编辑

什么时候抛出InvalidMonitorStateException异常?为什么?

评分

参与人数 1技术分 +1 收起 理由
EYE_SEE_YOU + 1

查看全部评分

6 个回复

倒序浏览
调用 wait ()/notify ()/notifyAll ()中的任何一个方法时,如果当前线程没有获得该对象的锁,那么就会抛出 IllegalMonitorStateException 的异常也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用 wait ()/notify ()/notifyAll ()时。由于该异常是 RuntimeExcpetion 的子类,所以该异常不一定要捕获(尽管你可以捕获只要你愿意作为 RuntimeException,此类异常不会在 wait (),notify (),notifyAll ()的方法签名提及。

评分

参与人数 1技术分 +1 收起 理由
EYE_SEE_YOU + 1

查看全部评分

回复 使用道具 举报
1、什么时候抛出InvalidMonitorStateException 异常,为什么?
答:调用wait ()/notify ()/notifyAll ()中的任何一个方法时,如果当前线程没有获得该对象的锁,那么就会抛出IllegalMonitorStateException 的异常(也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用wait ()/notify ()/notifyAll ()时)。由于该异常是RuntimeExcpetion 的子类,所以该异常不一定要捕获。作为RuntimeException,此类异常不会在wait (),notify (),notifyAll ()的方法签名提及。

2、在静态方法上使用同步时会发生什么事?
答:同步静态方法时会获取该类的“Class”对象,所以当一个线程进入同步的静态方法中时,线程监视器获取类本身的对象锁,其它线程不能进入这个类的任何静态同步方法。它不像实例方法,因为多个线程可以同时访问不同实例同步实例方法。

3、当一个同步方法已经执行,线程能够调用对象上的非同步实例方法吗?
答:可以,一个非同步方法总是可以被调用而不会有任何问题。实际上,Java 没有为非同步方法做任何检查,锁对象仅仅在同步方法或者同步代码块中检查。如果一个方法没有声明为同步,即使你在使用共享数据Java 照样会调用,而不会做检查是否安全,所以在这种情况下要特别小心。一个方法是否声明为同步取决于临界区访问(critial section access),如果方法不访问临界区(共享资源或者数据结构)就没必要声明为同步的。


希望对你有所帮助!

评分

参与人数 1技术分 +1 收起 理由
EYE_SEE_YOU + 1

查看全部评分

回复 使用道具 举报
我上次写代码的时候因为漏掉了关键字synchronied导致出现了这个异常
记得很清楚
回复 使用道具 举报
调用 wait ()/notify ()/notifyAll ()中的任何一个方法时,如果当前线程没有获得该对象的锁,那么就会抛出 IllegalMonitorStateException 的异常(也就是说程序在没有执行对象的任何同步块或者同步方法时,仍然尝试调用 wait ()/notify ()/notifyAll ()时)。由于该异常是 RuntimeExcpetion 的子类,所以该异常不一定要捕获(尽管你可以捕获只要你愿意).作为 RuntimeException,此类异常不会在 wait (),notify (),notifyAll ()的方法签名提及。
回复 使用道具 举报
其他人已经解释的很好了,在这里,我找了个不错的例子给你看,希望对你有帮助。
  • class IllegalMonitorStateExample
  • {
  • public static void main(String a[])
  • {
  • AnObject o = new AnObject();
  • Thread inc = new Thread(new IncrUser(o));
  • Thread dec = new Thread(new DecrUser(o));
  • inc.start();
  • dec.start();
  • }
  • }
  • class IncrUser implements Runnable
  • {
  • AnObject a ;
  • IncrUser()
  • {
  • }
  • IncrUser(AnObject a)
  • {
  • this.a = a;
  • }
  • public void run()
  • {
  • while(true)
  • {
  • try
  • {
  • [B]// a.wait();[/B]
  • a.incr();
  • Thread.sleep(1000);
  • [B] // a.notify(); //[/B]
  • }
  • catch(InterruptedException ie)
  • {
  • ie.printStackTrace();
  • }
  • }
  • }
  • }
  • class DecrUser implements Runnable
  • {
  • AnObject a ;
  • DecrUser()
  • {
  • }
  • DecrUser(AnObject a)
  • {
  • this.a = a;
  • }
  • public void run()
  • {
  • while(true)
  • {
  • try
  • {
  • a.decr();
  • Thread.sleep(1000);
  • }
  • catch(InterruptedException ie)
  • {
  • ie.printStackTrace();
  • }
  • }
  • }
  • }
  • class AnObject{
  • int myNum = 0;
  • synchronized void incr() throws InterruptedException
  • {
  • if(myNum!=0)
  • {
  • System.out.println("ready to incr but muNum not zero +++++++++++++++");
  • wait();
  • }
  • myNum++;
  • print("produced : ");
  • notify();
  • }
  • synchronized void decr() throws InterruptedException
  • {
  • if(myNum==0)
  • {
  • System.out.println("ready to decr but myNum not 1 ----------");
  • wait();
  • }
  • myNum--;
  • print("consumed : ");
  • notify();
  • }
  • void print(String s)
  • {
  • System.out.println(s + " "+myNum);
  • }
  • }



评分

参与人数 1技术分 +1 收起 理由
杨增坤 + 1

查看全部评分

回复 使用道具 举报
对于是否抛出异常,首先要判断继承的父类是否抛出了该异常,如果没有,子类是不可以抛出该异常的。
如果父类没有抛出该异常或抛出的不是该异常的父类,则需要在此类的子类中try-catch。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马