关于java.lang.IllegalMonitorStateException异常说明(三)

1、异常原因及解释

首先你要了解这个异常为什么会抛出,这个异常会在三种情况下抛出:
1>当前线程不含有当前对象的锁资源的时候,调用obj.wait()方法;
2>当前线程不含有当前对象的锁资源的时候,调用obj.notify()方法。
3>当前线程不含有当前对象的锁资源的时候,调用obj.notifyAll()方法。

java.lang.IllegalMonitorStateException是在调用object的wait和notify,notifyAll方法的时候可能会出现的异常。 在调用上述三个方法的时候,线程必须获得该对象的对象级别锁,换句话说,出现这个异常的原因是因为,调用wait和notify,notifyAll的对象没有在同步方法(synchronized修饰的方法)或者同步代码块(synchronized(x){})中。

wait()和notify()方法的调用必须具有内置锁 synchronized(this) 的代码块内或同步方法才能调用,否则就会报该错误。

如果用了显式锁 Lock 就不要用 wait() 和 notify() 了,它们是两套加锁机制,不能混着用的。

2、对象级别加锁

想要获取该对象的对象级别锁,即直接调用Object对象的上述三个方法,也就只有在同步方法或同步代码块中。(同步方法或同步代码块以当前对象this作为同步监视器)。

 3、调用某个对象的wait方法

如果要调用某个对象的wait方法,那么必须这么调用:

Object lock = new Object();
 synchronized(lock){
 lock.wait();
 }

如果是
Object lock = new Object();
synchronized(lock){
this.wait();
}
报错

4、举例

 1 package com.asd.reserve.pojo.thread;
 2 
 3 /**
 4  * @author zs
 5  * @date 2019/11/15 14:37
 6  */
 7 public class MyThread31 extends Thread
 8 {
 9     private Object lock;
10 
11     public MyThread31(Object lock)
12     {
13         this.lock = lock;
14     }
15 
16     public void run() {
17         ThreadDomain31 td = new ThreadDomain31();
18         td.testMethod(lock);
19     }
20 
21     public static void main(String[] args)
22     {
23         Object lock = new Object();
24         MyThread31 mt0 = new MyThread31(lock);
25         MyThread31 mt1 = new MyThread31(lock);
26         mt0.start();
27         try {
28             Thread.sleep(100);
29         } catch (InterruptedException e) {
30             e.printStackTrace();
31         }
32         mt1.start();
33     }
34 }
35 
36 package com.asd.reserve.pojo.thread;
37 
38 /**
39  * @author zs
40  * @date 2019/11/15 14:37
41  */
42 public class ThreadDomain31 {
43     public void testMethod(Object lock)
44     {
45         try
46         {
47             synchronized (lock) {
48                 System.out.println(Thread.currentThread().getName() + " Begin wait()");
49                 //lock.notify();
50                 //Thread.sleep(1000);
51                 lock.wait();
52                 Class<? extends ThreadDomain31> aClass = this.getClass();
53                 String name = aClass.getName();
54                 //super.wait();//调用此方法时,就会抛出该异常,因为当前的锁资源是lock。改成synchronized (this)可调用
55                 System.out.println(Thread.currentThread().getName() + " End wait");
56                 //lock.notify();
57             }
58         }
59         catch (InterruptedException e)
60         {
61             e.printStackTrace();
62         }
63     }
64 }

 

posted @ 2019-11-15 16:51  慎终若始  阅读(12861)  评论(1编辑  收藏  举报