5

私は 2 つのスレッドを設計しています。1 つはプレーヤーの名前を取得する必要があり、2 番目のスレッドは続行するために名前が設定されるのを待つ必要がありますが、最初のスレッドの notify() はすべて IllegalMonitorStateException エラーをスローしています。

private NameFecth nameFetch;
private UseName useName;
private Object nameSetLock; 
public static void method{
   nameSetLock = new Object()
   nameFetch = new NameFetch(nameSetLock);
   useName = new UseName(nameSetLock);
   Thread nameFetchThread = new Thread(nameFetch);
   nameFetchThread.start();
   Thread useNameThread = new Thread(useName);
   useNameThread.start();
}

public class NameFetch implements Runnable{
    /*variables and constructers*/

    public void run(){
       /*get name and set the variable somehow*/
       synchronized(nameSetLock){
         notifyAll();
       }
    }
}

public class UseName implements Runnable{
    /*variables and constructers*/

   public void run(){
     while(!nameBeenSet){
       synchronized(nameSetLock){
         try{
           wait();
         }catch(InterruptedException e) {}
       }
     }

}

私は何を間違えましたか?

4

4 に答える 4

16

あなたは、待っていることや通知していることに同期せずに電話waitをかけています。notifyに記載されているObject.notifyAllとおり:

例外:
IllegalMonitorStateException- 現在のスレッドがこのオブジェクトのモニターの所有者でない場合。

したがって、この:

synchronized(nameSetLock){
  notifyAll();
}

次のようにする必要があります。

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

... についても同様ですwait。現在のコードは、実際のコードを投稿していないことを示唆していsyncronizedます。コードを入力する際に​​、実際に問題を変更した可能性があります。その場合は、質問をより代表的なものに編集する必要があります。synchronized

于 2013-08-13T12:52:23.607 に答える
1

の JavaDoc からIllegalStateException

  Thrown to indicate that a thread has attempted to wait on an object's 
  monitor or to notify other threads waiting on an object's  monitor
  without owning the specified monitor. 

そのオブジェクトをロックせずに、wait() と notifyAll() を呼び出そうとしています。

@Jon が提案したことを試してみてください。

于 2013-08-13T12:57:07.840 に答える
1

ロックを誤って使用していることが問題のようです。同期ブロックは nameSetLock にあり、NameFetch オブジェクト インスタンスで notifyall を呼び出しています (これは、同期 (this) と呼ばれます)。

ロックと nameSetLock.notifyAll を使用して通知する場合は、nameSetLock.wait を実行する必要があります。

于 2013-08-13T12:51:11.710 に答える