1.概述
在这个简短的教程中,我们将学习java.lang.IllegalMonitorStateException.
我们将创建一个简单的发送方-接收方应用程序,该应用程序将引发此异常。然后,我们将讨论防止这种情况的可能方法。最后,我们将展示如何正确实现这些发送者和接收者类。
2.什么时候抛出此异常?
IllegalMonitorStateException
与Java中的多线程编程有关。如果我们有一个monitor
,则抛出此异常,以表明某个线程试图等待,或者通知其他线程在该监视器上等待而不拥有它。用简单的话来说,如果我们在synchronized
块Object
wait()
, notify(),
或notifyAll()
方法之一,则会得到此异常。
现在让我们构建一个抛出IllegalMonitorStateException
的示例。为此,我们将同时使用wait()
和notifyAll()
方法来同步发送方和接收方之间的数据交换。
首先,让我们看一下保存将要发送的消息Data
public class Data {
private String message;
public void send(String message) {
this.message = message;
}
public String receive() {
return message;
}
}
其次,让我们创建在被调用时IllegalMonitorStateException
.
为此,我们将调用notifyAll()
方法,而不将其包装在synchronized
块中:
class UnsynchronizedSender implements Runnable {
private static final Logger log = LoggerFactory.getLogger(UnsychronizedSender.class);
private final Data data;
public UnsynchronizedSender(Data data) {
this.data = data;
}
@Override
public void run() {
try {
Thread.sleep(1000);
data.send("test");
data.notifyAll();
} catch (InterruptedException e) {
log.error("thread was interrupted", e);
Thread.currentThread().interrupt();
}
}
}
接收者还将引发IllegalMonitorStateException.
与前面的示例类似,我们将在synchronized
块wait()
public class UnsynchronizedReceiver implements Runnable {
private static final Logger log = LoggerFactory.getLogger(UnsynchronizedReceiver.class);
private final Data data;
private String message;
public UnsynchronizedReceiver(Data data) {
this.data = data;
}
@Override
public void run() {
try {
data.wait();
this.message = data.receive();
} catch (InterruptedException e) {
log.error("thread was interrupted", e);
Thread.currentThread().interrupt();
}
}
public String getMessage() {
return message;
}
}
最后,让我们实例化这两个类并在它们之间发送一条消息:
public void sendData() {
Data data = new Data();
UnsynchronizedReceiver receiver = new UnsynchronizedReceiver(data);
Thread receiverThread = new Thread(receiver, "receiver-thread");
receiverThread.start();
UnsynchronizedSender sender = new UnsynchronizedSender(data);
Thread senderThread = new Thread(sender, "sender-thread");
senderThread.start();
senderThread.join(1000);
receiverThread.join(1000);
}
当我们尝试运行这段代码时,我们将同时从UnsynchronizedReceiver
和UnsynchronizedSender
类IllegalMonitorStateException
[sender-thread] ERROR 1ju.org.exceptions.illegalmonitorstate.UnsynchronizedSender - illegal monitor state exception occurred
java.lang.IllegalMonitorStateException: null
at java.base/java.lang.Object.notifyAll(Native Method)
at 1ju.org.exceptions.illegalmonitorstate.UnsynchronizedSender.run(UnsynchronizedSender.java:15)
at java.base/java.lang.Thread.run(Thread.java:844)
[receiver-thread] ERROR 1ju.org.exceptions.illegalmonitorstate.UnsynchronizedReceiver - illegal monitor state exception occurred
java.lang.IllegalMonitorStateException: null
at java.base/java.lang.Object.wait(Native Method)
at java.base/java.lang.Object.wait(Object.java:328)
at 1ju.org.exceptions.illegalmonitorstate.UnsynchronizedReceiver.run(UnsynchronizedReceiver.java:12)
at java.base/java.lang.Thread.run(Thread.java:844)
3.如何修复
**要摆脱IllegalMonitorStateException,
我们需要synchronized
块内进行wait()
, notify(),
和notifyAll()
**考虑到这一点,让我们看一下Sender
类的正确实现应如何:
class SynchronizedSender implements Runnable {
private final Data data;
public SynchronizedSender(Data data) {
this.data = data;
}
@Override
public void run() {
synchronized (data) {
data.send("test");
data.notifyAll();
}
}
}
请注意,我们在Data
synchronized
块,我们稍后将其称为notifyAll()
方法。
让我们以相同的方式Receiver
class SynchronizedReceiver implements Runnable {
private static final Logger log = LoggerFactory.getLogger(SynchronizedReceiver.class);
private final Data data;
private String message;
public SynchronizedReceiver(Data data) {
this.data = data;
}
@Override
public void run() {
synchronized (data) {
try {
data.wait();
this.message = data.receive();
} catch (InterruptedException e) {
log.error("thread was interrupted", e);
Thread.currentThread().interrupt();
}
}
}
public String getMessage() {
return message;
}
}
如果我们再次创建两个类并尝试在它们之间发送相同的消息,则一切正常,并且不会引发异常。
4 结论
在本文中,我们了解了导致IllegalMonitorStateException
原因以及如何防止它。
0 评论