2017-11-21 6 views
2

Ich lerne immer noch auf Threads folgenden Java-Tutorials der Orakel-Website.java.lang.IllegalMonitorStateException on notifyAll() Methode

Mit Bezug auf die wait() und notifyAll() habe ich etwas Code geschrieben. Meine erwartete Ausgabe ist Drucken Sie die Nachricht in run() 10-mal und drucken Sie die "Fun Stopped by StopFun Thread" Nachricht in guardedJoy(GuardedBlock guardedBlock) Methode, wenn die "Freude" auf false in der run-Methode gesetzt.

Dies ist mein Code.

public class GuardedBlock { 

private boolean joy = true; 

public synchronized void guardedJoy(GuardedBlock guardedBlock) { 

    System.out.println(Thread.currentThread().getName() + " Guard Joy method started"); 
    while (guardedBlock.joy) { 
     try { 
      System.out.println(Thread.currentThread().getName() + " Going to waiting state"); 
      guardedBlock.wait(); 
     } catch (InterruptedException ex) { 
     } 
    } 
    System.out.println("Fun stopped by StopFun Thread"); 
} 

private static class StopFun implements Runnable { 

    private GuardedBlock guardedBlock; 

    public StopFun(GuardedBlock guardedBlock) { 
     this.guardedBlock = guardedBlock; 
    } 

    @Override 
    public void run() { 

     for (int x = 0; x < 100; x++) { 
      try { 
       Thread.sleep(500); 
       System.out.println("Allowing fun since its only " + x + " times - " + Thread.currentThread().getName()); 

       if (x == 10) { 
        guardedBlock.joy = false; 
        guardedBlock.notifyAll(); 
        break; 
       } 
      } catch (InterruptedException ex) { 
      } 
     } 
    } 
} 

public static void main(String[] args) { 

    GuardedBlock guardedBlock = new GuardedBlock(); 

    StopFun sf = new StopFun(guardedBlock); 
    Thread stopFun = new Thread(sf); 
    stopFun.start(); 

    guardedBlock.guardedJoy(guardedBlock); 
    } 
} 

Der Code in der run-Methode läuft gut, aber danach löst es eine Ausnahme wie folgt aus.

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException 
    at java.lang.Object.notifyAll(Native Method) 
    at Synchronization.GuardedBlock$StopFun.run(GuardedBlock.java:38) 
    at java.lang.Thread.run(Thread.java:748) 

Ich ging durch einige Fragen und Antworten auf der Website wie this und this aber kann nicht herausfinden, was genau ich falsch mache. Eine Hilfe wird sehr geschätzt.

Danke.

+0

[Die Dokumentation] (https://docs.oracle.com/javase/9/docs/api/java/lang/Object.html#notifyAll--) ist dein Freund: "** Wirf: ** IllegalMonitorStateException - Wenn der aktuelle Thread nicht der Eigentümer des Monitors dieses Objekts ist. " – VGR

Antwort

3

wait() und notify()/notifyAll() muss in einem synchronized Block aufgerufen werden.

synchronized (guardedBlock) { 
    guardedBlock.notifyAll(); 
} 

und so weiter.

+0

Danke für die Antwort. Ich habe eine Frage though.wait() ist bereits in einer synchronisierten Methode. Muss ich also einen separaten synchronisierten Block einführen? –

+0

Sorry, ich habe nicht gesehen, dass die Methode synchronisiert ist. Aber es wird auf 'this' synchronisiert, und' wait() 'wird auf' guardedBlock' aufgerufen. In Ihrem Programm ist es so, dass 'guardedBlock '' ''' im Moment des Aufrufs mit 'guardedBlock.guardedJoy (guardedBlock);' übereinstimmt, und es sollte ohne einen zusätzlichen 'synchronisierten' Block funktionieren, aber das ist ein bisschen zerbrechlich . Und natürlich muss 'notifyAll()' auch unter Synchronisation sein. –

+0

Es ist besser, 'guardedBlock.joy = false;' im synchronisierten Block zu platzieren. –

Verwandte Themen