2017-05-30 2 views
1

あなたは、このコードはjava.util.NoSuchElementExceptionを投げ、その場合には教えてくださいでした:ランダムjava.util.NoSuchElementException()

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

私のループは常にへのエンキュー方法を待っています要素を追加した後にnotifyAllを呼び出します。しかし時々、呼び出すときにjava.util.NoSuchElementExceptionが発生するmyList.removeLast()

+0

あなたのリストにエントリがない場合は、 – Jens

+0

エントリのサイズがない場合は0になり、プログラムは待機しますか? (myList.size()== 0) } – Djoz

+0

'wait'が完了したのに' myList'がまだ空の場合... 'wait'は' enQueue'が呼び出されたときにのみ起こると確信していますか? –

答えて

4

the recommended patternに固執し、偽のウェークアップを避けるために条件をwhileに入れてください。

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

ありがとう、はい私は間違いなく私の状態を入れます。私の質問は、これらの偽の起床についてです。私の例では、enQueueメソッドだけが通知を呼び出すと確信しているときに、どのような起床が起こる可能性があります。 – Djoz

+0

@Youssこれは私が投稿したリンクに説明されています。 'notify'が呼び出されていなくても' wait'が返ることがあります。問題の別の理由は、質問に表示されていない場所でコード内で 'notify'を呼び出す場合です。 – assylias

1

問題は、このコード行は、もはや同期により保護されていない:リスト上の待機を呼び出す

Object elem = myList.removeLast(); 

は()ロックの所有権を解放するので、別のスレッドが通知部分に到達することができますあなたのコードの。これはまた、複数のスレッドが待機していて、一度に通知されることを意味します。これらは並行してリストのremoveLast()を実行しようとします。リスト内の要素よりも多くのスレッドが待機していると、記述されたエラーが発生します。

関連する問題