IllegalMonitorStateException i Java

1. Oversigt

I denne korte vejledning lærer vi om java.lang.IllegalMonitorStateException.

Vi opretter en simpel afsender-modtager-applikation, der kaster denne undtagelse. Derefter diskuterer vi mulige måder at forhindre det på. Endelig viser vi, hvordan vi implementerer disse afsender- og modtagerklasser korrekt.

2. Hvornår kastes det?

Det IllegalMonitorStateException er relateret til multithreading programmering i Java. Hvis vi har en overvåge vi vil synkronisere, denne undtagelse kastes for at indikere, at en tråd forsøgte at vente eller at underrette andre tråde, der ventede på den skærm, uden at eje den. Med enklere ord får vi denne undtagelse, hvis vi kalder en af vente(), underrette(), eller notifyAll () metoder til Objekt klasse uden for en synkroniseret blok.

Lad os nu bygge et eksempel, der kaster et IllegalMonitorStateException. Til dette bruger vi begge dele vente() og notifyAll () metoder til at synkronisere dataudvekslingen mellem en afsender og en modtager.

Lad os først se på Data klasse, der indeholder den besked, vi sender:

offentlig klasse Data {privat streng besked; offentlig tomrumsudsendelse (streng besked) {this.message = meddelelse; } offentlig streng modtage () {returmeddelelse; }}

For det andet, lad os oprette afsenderklassen, der kaster en IllegalMonitorStateException når påberåbt. Til dette formål kalder vi notifyAll () metode uden at indpakke den i en synkroniseret blok:

klasse UnsynchronizedSender implementerer Runnable {private static final Logger log = LoggerFactory.getLogger (UnsychronizedSender.class); private endelige data data; public UnsynchronizedSender (Data data) {this.data = data; } @ Override public void run () {prøv {Thread.sleep (1000); data.send ("test"); data.notifyAll (); } fange (InterruptedException e) {log.error ("tråden blev afbrudt", e); Thread.currentThread (). Interrupt (); }}}

Modtageren vil også kaste et IllegalMonitorStateException. På samme måde som det foregående eksempel ringer vi til vente() metode uden for en synkroniseret blok:

offentlig klasse UnsynchronizedReceiver implementerer Runnable {private static final Logger log = LoggerFactory.getLogger (UnsynchronizedReceiver.class); private endelige data data; privat streng besked; public UnsynchronizedReceiver (Data data) {this.data = data; } @ Overstyr offentlig ugyldig kørsel () {prøv {data.wait (); this.message = data.receive (); } fange (InterruptedException e) {log.error ("tråden blev afbrudt", e); Thread.currentThread (). Interrupt (); }} public String getMessage () {return message; }}

Lad os endelig instantiere begge klasser og sende en besked mellem dem:

public void sendData () {Data data = new Data (); UnsynchronizedReceiver receiver = ny UnsynchronizedReceiver (data); TrådmodtagerTråd = ny tråd (modtager, "modtagertråd"); receiverThread.start (); UnsynchronizedSender sender = ny UnsynchronizedSender (data); Tråd senderThread = ny tråd (afsender, "afsender-tråd"); senderThread.start (); senderThread.join (1000); receiverThread.join (1000); }

Når vi prøver at køre dette stykke kode, modtager vi en IllegalMonitorStateException fra begge UnsynchronizedReceiver og UnsynchronizedSender klasser:

[sender-thread] FEJL com.baeldung.exceptions.illegalmonitorstate.UnsynchronizedSender - illegal monitor state undtagelse opstod java.lang.IllegalMonitorStateException: null at java.base / java.lang.Object.notifyAll (Native Method) at com.baeldung.exceptions .illegalmonitorstate.UnsynchronizedSender.run (UnsynchronizedSender.java:15) at java.base / java.lang.Thread.run (Thread.java:844) [receiver-thread] FEJL com.baeldung.exceptions.illegalmonitorstate.UnsynchronizedReceiver - illegal monitor tilstandsundtagelse opstod java.lang.IllegalMonitorStateException: null ved java.base / java.lang.Object.wait (Native Method) ved java.base / java.lang.Object.wait (Object.java:328) ved com.baeldung. undtagelser.illegalmonitorstate.UnsynchronizedReceiver.run (UnsynchronizedReceiver.java:12) at java.base / java.lang.Thread.run (Thread.java:844) 

3. Sådan løses det

For at slippe af med IllegalMonitorStateException, vi er nødt til at foretage hvert opkald til vente(), underrette(), og notifyAll () metoder inden for en synkroniseret blok. Med dette i tankerne, lad os se, hvordan den korrekte implementering af Afsender klasse skal se ud:

klasse SynchronizedSender implementerer Runnable {private final Data data; offentlig SynchronizedSender (datadata) {denne.data = data; } @ Override public void run () {synkroniseret (data) {data.send ("test"); data.notifyAll (); }}}

Bemærk, at vi bruger synkroniseret blokere på det samme Data eksempel vi senere kalder det notifyAll () metode.

Lad os rette op på Modtager på samme måde:

klasse SynchronizedReceiver implementerer Runnable {private static final Logger log = LoggerFactory.getLogger (SynchronizedReceiver.class); private endelige data data; privat streng besked; offentlig SynchronizedReceiver (Data data) {this.data = data; } @ Override public void run () {synkroniseret (data) {prøv {data.wait (); this.message = data.receive (); } fange (InterruptedException e) {log.error ("tråden blev afbrudt", e); Thread.currentThread (). Interrupt (); }}} offentlig String getMessage () {returmeddelelse; }}

Hvis vi igen opretter begge klasser og prøver at sende den samme besked imellem dem, fungerer alt godt, og ingen undtagelse kastes.

4. Konklusion

I denne artikel lærte vi, hvad der forårsager det IllegalMonitorStateException og hvordan man forhindrer det.

Som altid er koden tilgængelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found