IllegalMonitorStateException异常,我们先看下API的定义:
/**
* Thrown to indicate that a thread has attempted to wait on an
* object's monitor or to notify other threads waiting on an object's
* monitor without owning the specified monitor.
*
* @author unascribed
* @see java.lang.Object#notify()
* @see java.lang.Object#notifyAll()
* @see java.lang.Object#wait()
* @see java.lang.Object#wait(long)
* @see java.lang.Object#wait(long, int)
* @since JDK1.0
*/
public class IllegalMonitorStateException extends RuntimeException
大致意思就是说抛出这个异常表明线程尝试等待一个对象的监视器或者去通知其他正在等待这个对象监视器的线程时,但是没有拥有这个监视器的所有权。
monitor翻译成监视器,可能大家会有些疑惑。我们可以换一个角度来解释这个问题,大家都知道Java中每个类和对象都有一个同步锁,只有获取到调用同步锁,调用wait和notify方法才行(下一篇专门讲一下Java的锁)。下面我们看几个例子就明白是怎么回事了:
实例1:
调用所属对象的wait和notify方法。
//所属对象的情况
public synchronized void notifySlef(){
this.notify();
}
或
public synchronized void waitSlef(){
this.wait();
}
//其他对象的情况
public Object lock = new Object();
public synchronized void notifySlef(){
synchronized(lock) {
lock.notify();
}
}
或
public Object lock = new Object();
public synchronized void waitSlef(){
synchronized(lock) {
lock.wait();
}
}
因为在waitSlef和notifySlef方法使用了synchronized获取了所属对象或其他对象的同步锁,所以调用wait()或者notify()方法是不会报错的。
实例2:
调用类的notify和wait方法。
public static synchronized void notifyClass() {
Test.class.notify();
}
或者
public void waitClass() {
synchronized (Test.class) {
Test.class.wait();
}
}
调用类的wait和notify方法,就要获取到类的锁。
总之,我们可以把API中所说的监视器(monitor)理解成同步锁。想要执行某个对象的notify(), notifyAll(),wait(), wait(long), wait(long, int)方法
就必须获取该对象的锁,需要使用synchronized,不然就会抛出IllegalMonitorStateException异常。
分享到:
相关推荐
这就是为什么只有在同步的块或者方法中才能调用 wait/notify 等方法,否则会抛出 java.lang.IllegalMonitorStateException 异常的原因。 在 Java 1.5 之后版本中,JVM 内置锁做了重大的优化,如锁粗化、锁消除、轻...
需要注意的是,wait()方法只能在同步块或同步方法中调用,否则将抛出java.lang.IllegalMonitorStateException异常。这是因为wait()方法需要在获得同步锁后才能调用,以确保线程的安全。 notify()方法 notify()方法...
这些异常大多数都是`java.lang.Throwable`的子类,例如`ArrayIndexOutOfBoundsException`和`NullPointerException`。开发者可以通过`try-catch-finally`语句块来捕获和处理这些异常,保证程序的健壮性。 Java的接口...
`java.lang.RuntimeException: Problem`是异常的信息,不会直接打印到控制台。 - **选项B**:错误。`run. java.lang.RuntimeException: Problem`虽然包含了`run.`,但是没有正确地表示出`End of method.`的输出顺序...
Sun Certified Programmer for the Java Platform, Standard ...这些知识点涵盖了Java多线程编程中的关键概念,包括线程生命周期、异常处理、死锁以及对象监视器的使用。掌握这些知识对于通过SCJP6认证考试至关重要。
通过这些解析,我们可以了解到Java多线程编程的一些基本概念和常见陷阱,例如如何处理异常、死锁的预防以及`synchronized`和`wait()/notify()`的正确使用方式等。对于准备SCJP认证考试的学习者来说,掌握这些知识点...
Java提供了两种主要的等待唤醒机制:`wait()`、`notify()`和`notifyAll()`,它们都是`java.lang.Object`类的方法。这些方法必须在同步块或同步方法中使用,以避免因非法访问而导致的错误。 1. `wait()`方法:当一个...
java.lang.RuntimeException: Problem"。 2. 死锁的理解与预防: 死锁是多线程编程中的一个关键问题,它发生在两个或多个线程相互等待对方释放资源而无法继续执行的情况。问题3中的选项A和F正确阐述了死锁的特性...
需要注意的是,wait() 方法必须放置在 synchronized 块中,否则会在程序 runtime 时抛出“java.lang.IllegalMonitorStateException”异常。 wait() 方法可以通过 notify 或者 notifyAll 或者指定睡眠时间来唤醒当前...
- 调用`wait()`方法前必须获取监视器锁,否则会抛出`IllegalMonitorStateException`异常。 ##### 7. `finalize()` - **方法签名**:`protected void finalize() throws Throwable;` - **功能**:在垃圾收集器确定...
这些方法必须在`synchronized`代码块或方法中调用,因为它们需要在持有对象锁的情况下执行,否则会抛出`java.lang.IllegalMonitorStateException`异常。 1. `wait()`:调用此方法的线程会释放它持有的对象锁,进入...
- `run()`方法包含于`java.lang.Thread`中,是这个线程的功能,需要用户重写。 - `start()`方法用于启动线程,通常在其他地方(如`main()`函数)调用此方法,不需要用户重写。 - 直接调用`t1.run();`不会启动新的线程...
- `Thread.sleep(millisecond)` 方法来自 `java.lang.Thread` 类,它使当前正在执行的线程暂停指定的毫秒数,并将线程的执行权交还给操作系统。 - 睡眠结束后,线程并不会自动恢复执行,而是需要等待系统的调度。 ...
在Java中,`wait()` 和 `notify()` 方法是实现线程间通信和协作的重要工具,它们属于 `java.lang.Object` 类,这意味着所有类都默认继承了这两个方法。本文将详细探讨如何使用 `wait()` 和 `notify()` 来控制子线程...