当我们在使用多线程中,有时会抱这个错误:
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.flower.dujiaohao.utils.threadstudy.ThreadStudy.main(ThreadStudy.java:18)
java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.flower.dujiaohao.utils.threadstudy.ThreadStudy.run(ThreadStudy.java:10)
错误的主要原因为:
违法的监控状态异常。当某个线程试图等待一个自己并不拥有的对象(O)的监控器或者通知其他线程等待该对象(O)的监控器时,抛出该异常。
以上错误贴出对应的代码:
public class ThreadStudy extends Thread{
public void run(){
// synchronized (this) {
// }
System.out.println("要执行跑了");
notify();
}
public static void main(String[] args) throws Exception{
ThreadStudy s = new ThreadStudy();
System.out.println("开始执行了!");
s.start();
System.out.println("要等待了!");
s.wait();
System.out.println("结束了");
// synchronized (s) {
// }
}
}
根据错误提示我们看到其中行10和行18有错,也就是对应的方法notify()和s.wait(),为什么呢?根据源码我们能得出结论
* The current thread must own this object's monitor. The thread
* releases ownership of this monitor and waits until another thread
* notifies threads waiting on this object's monitor to wake up
* either through a call to the {@code notify} method or the
* {@code notifyAll} method. The thread then waits until it can
* re-obtain ownership of the monitor and resumes execution.
* <p>
* As in the one argument version, interrupts and spurious wakeups are
* possible, and this method should always be used in a loop:
* <pre>
* synchronized (obj) {
* while (<condition does not hold>)
* obj.wait();
* ... // Perform action appropriate to condition
* }
* </pre>【含义:当前线程必须拥有此对象的锁,直到另一个线程通知线程在这个对象锁等待醒来】
public final void wait() throws InterruptedException {
wait(0);
}
/**
* Wakes up a single thread that is waiting on this object's
* monitor. If any threads are waiting on this object, one of them
* is chosen to be awakened. The choice is arbitrary and occurs at
* the discretion of the implementation. A thread waits on an object's
* monitor by calling one of the {@code wait} methods.
* <p>
* <ul>
* <li>By executing a synchronized instance method of that object.
* <li>By executing the body of a {@code synchronized} statement
* that synchronizes on the object.
* <li>For objects of type {@code Class,} by executing a
* synchronized static method of that class.
* </ul>
* <p>【含义:唤醒一个线程正在等待这个对象的锁,前提自己也必须拥有这个锁对象】
public final native void notify();
那么由此我们可以知道,object类中wait()和notify()方法使用规律
1.当前线程”在调用wait()/notify()时,必须拥有该对象的同步锁
2.使用时要在同步快中使用
好了刚才上面的正确代码没有贴上这里补上:
public class ThreadStudy extends Thread{
public void run(){
synchronized (this) {
System.out.println("要执行跑了");
notify();
}
}
public static void main(String[] args) throws Exception{
ThreadStudy s = new ThreadStudy();
synchronized (s) {
System.out.println("开始执行了!");
s.start();
System.out.println("要等待了!");
s.wait();
System.out.println("结束了");
}
}
}
这里抛出一个问题,能说一下这段代码执行的输出顺序吗?为什么呢?可以留言告诉我哦 O(∩_∩)O~
。
。
。
。
。
。
。
。
。
。
。
。
。
答案:
开始执行了!
要等待了!
要执行跑了
结束了