拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Java中的IllegalMonitorStateException

Java中的IllegalMonitorStateException

白鹭 - 2021-11-24 726 0 0

1.概述

在这个简短的教程中,我们将学习java.lang.IllegalMonitorStateException.

我们将创建一个简单的发送方-接收方应用程序,该应用程序将引发此异常。然后,我们将讨论防止这种情况的可能方法。最后,我们将展示如何正确实现这些发送者和接收者类。

2.什么时候抛出此异常?

IllegalMonitorStateException与Java中的多线程编程有关。如果我们有一个monitor ,则抛出此异常,以表明某个线程试图等待,或者通知其他线程在该监视器上等待而不拥有它。用简单的话来说,如果我们在synchronizedObject 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.与前面的示例类似,我们将在synchronizedwait()

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);

 }

当我们尝试运行这段代码时,我们将同时从UnsynchronizedReceiverUnsynchronizedSenderIllegalMonitorStateException

[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 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *