2017-05-30 5 views
1

Könnten Sie mir bitte sagen, in welchem ​​Fall dieser Code eine java.util.NoSuchElementException werfen:Zufall java.util.NoSuchElementException auch mit Warte mit()

public class StackTest { 

    private LinkedList<Object> myList = new LinkedList<Object>(); 
    public StackTest() { 

     Thread testStack = new Thread() { 
      @Override 
      public void run() { 
       while (true) 
       { 
        synchronized (myList) 
        { 
         try { 
          if (myList.size() == 0) 
          { 
           myList.wait(); 
          } 
          Object elem = myList.removeLast(); 
         } catch (Exception e) { 
          e.printStackTrace(); 
         } 
        } 
       } 
      } 
     }; 
     testStack.start(); 
    } 

    public void enQueue(Object o) 
    { 
     synchronized(myList) 
     { 
      myList.addFirst(o); 
      myList.notifyAll(); 
     } 
    } 
} 

Meine Schleife immer für die Enqueue Methode wartet Rufen Sie notifyAll auf, nachdem Sie ein Element hinzugefügt haben. Aber von Zeit zu Zeit habe ich eine java.util.NoSuchElementException wenn myList.removeLast()

Aufruf
+0

Wenn es keinen Eintrag mehr in Ihrer Liste gibt? – Jens

+0

Wenn es keine Eintragsgröße gibt, wird 0 sein und das Programm wird warten? if (myList.size() == 0) { myList.wait(); } – Djoz

+0

Wenn die 'wait' beendet ist, aber' myList' noch leer ist ... Sind Sie sicher, dass 'wait' nur passiert, wenn' enQueue' aufgerufen wird? –

Antwort

4

Sie auf the recommended pattern bleiben sollen und setzen Sie Ihren Zustand in einem while unechte Wakeups zu vermeiden.

synchronized (myList) { 
    try { 
     while (myList.size() == 0) { 
      myList.wait(); 
     } 
     Object elem = myList.removeLast(); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

Danke, Ja, ich werde auf jeden Fall meinen Zustand in eine Weile stellen. Meine Frage betrifft diese unechten Wakeups. In meinem Beispiel könnte die Art von Wakeups passieren, wenn ich sicher bin, dass nur die Methode enQueue die Benachrichtigung aufruft. – Djoz

+0

@Youss Es wird in dem Link, den ich gepostet habe, erklärt. 'wait' kann zurückkommen, auch wenn' notify' nicht aufgerufen wurde. Beachten Sie, dass ein weiterer möglicher Grund für Ihr Problem darin besteht, dass Sie in Ihrem Code "notify" an einem Ort aufrufen, den Sie in Ihrer Frage nicht angezeigt haben. – assylias

1

Das Problem ist, diese Zeile Code ist nicht mehr geschützt durch den synchronisierten:

Object elem = myList.removeLast(); 

Aufruf wait() auf der Liste gibt den Besitz des Schlosses, so einen anderen Thread den Teil benachrichtigen erreichen deines Codes. Dies bedeutet auch, dass mehrere Threads warten können - und sofort benachrichtigt werden. Diese versuchen dann gleichzeitig, removeLast() auf Ihrer Liste auszuführen - was zu dem beschriebenen Fehler führen wird, wenn mehr Threads warten als Elemente in der Liste.

Verwandte Themen