Java中的IllegalMonitorStateException
- java
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
原因以及如何防止它。