IllegalMonitorStateException i Java

1. Oversikt

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

Vi oppretter en enkel avsender-mottaker-applikasjon som kaster dette unntaket. Deretter vil vi diskutere mulige måter å forhindre det på. Til slutt vil vi vise hvordan du implementerer disse avsender- og mottakerklassene riktig.

2. Når kastes det?

De IllegalMonitorStateException er relatert til multithreading programmering i Java. Hvis vi har en Observere vi vil synkronisere videre, dette unntaket blir kastet for å indikere at en tråd prøvde å vente eller å varsle andre tråder som ventet på skjermen, uten å eie den. Med enklere ord får vi dette unntaket hvis vi kaller et av vente(), gi beskjed(), eller notifyAll () metoder for Gjenstand klasse utenfor en synkronisert blokkere.

La oss nå bygge et eksempel som kaster et IllegalMonitorStateException. For dette bruker vi begge deler vente() og notifyAll () metoder for å synkronisere datautvekslingen mellom en avsender og en mottaker.

For det første, la oss se på Data klasse som inneholder meldingen vi skal sende:

offentlig klasse Data {privat strengmelding; offentlig ugyldig sending (strengmelding) {this.message = melding; } offentlig streng motta () {returmelding; }}

For det andre, la oss lage avsenderklassen som kaster en IllegalMonitorStateException når påkalt. For dette formålet vil vi kalle notifyAll () metode uten å pakke den inn i en synkronisert blokkere:

klasse UnsynchronizedSender implementerer Runnable {private static final Logger log = LoggerFactory.getLogger (UnsychronizedSender.class); private endelige 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 ble avbrutt", e); Thread.currentThread (). Interrupt (); }}}

Mottakeren skal også kaste et IllegalMonitorStateException. På samme måte som i forrige eksempel, ringer vi til vente() metode utenfor a synkronisert blokkere:

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

Til slutt, la oss instansiere begge klassene og sende en melding mellom dem:

public void sendData () {Data data = new Data (); UnsynchronizedReceiver mottaker = ny UnsynchronizedReceiver (data); TrådmottakerTråd = ny tråd (mottaker, "mottaker-tråd"); receiverThread.start (); UnsynchronizedSender avsender = ny UnsynchronizedSender (data); Tråd senderThread = ny tråd (avsender, "sender-tråd"); senderThread.start (); senderThread.join (1000); receiverThread.join (1000); }

Når vi prøver å kjøre denne koden, mottar vi en IllegalMonitorStateException fra begge Usynkronisert mottaker og UnsynchronizedSender klasser:

[sender-thread] ERROR com.baeldung.exceptions.illegalmonitorstate.UnsynchronizedSender - illegal monitor state exception occurred 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] FEIL com.baeldung.exceptions.illegalmonitorstate.UnsynchronizedReceiver - illegal monitor tilstands unntak skjedde java.lang.IllegalMonitorStateException: null at java.base / java.lang.Object.wait (Native Method) at java.base / java.lang.Object.wait (Object.java:328) at com.baeldung. unntak.illegalmonitorstate.UnsynchronizedReceiver.run (UnsynchronizedReceiver.java:12) at java.base / java.lang.Thread.run (Thread.java:844) 

3. Hvordan fikser jeg det?

Å kvitte seg med IllegalMonitorStateException, vi trenger å ringe til vente(), gi beskjed(), og notifyAll () metoder innen a synkronisert blokkere. Med dette i tankene, la oss se hvordan riktig implementering av Avsender klassen skal se ut som:

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

Merk at vi bruker synkronisert blokker på det samme Data eksempel vi senere kaller det notifyAll () metode.

La oss fikse Mottaker på samme måten:

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

Hvis vi igjen lager begge klassene og prøver å sende den samme meldingen mellom dem, fungerer alt bra, og intet unntak blir kastet.

4. Konklusjon

I denne artikkelen lærte vi hva som forårsaker det IllegalMonitorStateException og hvordan du kan forhindre det.

Som alltid er koden tilgjengelig på GitHub.


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