1

fooオブザーバーを受け取り、オブザーバーがウェイクアップするまで現在のスレッドをスリープ状態にする次のメソッドがあります。

何らかの理由で、java.lang.IllegalMonitorStateException例外が発生し続けますfoo

public void foo(Observer o)
{
    Thread currentThread = Thread.currentThread();
    o.setThread(currentThread);
    // sleep until the observer wakes it
    currentThread.wait(2000);   // <<<<< Exception happens here
}

Observerオブジェクトは、currentThread.notifyAll()後で呼び出したときにObservable呼び出しますupdate

public class Observer
{
    private volatile Thread currentThread;
    // ... other code  ....

   public void setThread(Thread t)
   {
       currentThread = t;
   }

   public void update(Observable o)
   {
        currentThread.notify();
   }
}

ここで何が間違っているのですか?

4

5 に答える 5

3

wait(long)object のまたはメソッドを呼び出すときはいつでもnotify()、そのスレッドはそのオブジェクトのモニターを所有している必要があります。wait()したがって、オブジェクトを呼び出しているコードのブロックを宣言する必要がありますsynchronized。だからあなたの方法

public void foo(Observer o) 

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

public void foo(Observer o)
{
    Thread currentThread = Thread.currentThread();
    o.setThread(currentThread);
    // sleep until the observer wakes it
    synchronized(currentThread)
    {
      currentThread.wait(2000);   
    }
 }

更新:
あなたの要件に従って、 object を呼び出すことをお勧めwaitObserverます。したがって、コードは次のfooようになります。

public void foo(Observer o)
{
    synchronized(o)
    {
      o.wait();//Don't pass time as parameter. Let only the Observer object to wake it up.
    }
 }

Observer クラスは次のように定義する必要があります。

public class Observer
{
    // ... other code  ....

   /*public void setThread(Thread t)
   {
       currentThread = t;
   }*/
   public synchronized void update(Observable o)
   {
        notify();//Will wake up the Thread waiting on the current Object of Observer
   }
}
于 2013-04-08T19:06:46.900 に答える
1

使用しないことをお勧めします。waitまたはnotify、低レベルであり、適切に実装されていないとすぐに汚れてしまうためです。バイナリセマフォで解決できます。

Semaphore sem = new Semaphore(0);
public void foo(Semaphore f){
    f.acquire();
}

f.release他のスレッドは、他のスレッドのブロックを解除するために後で呼び出すことができます

于 2013-04-08T19:11:00.887 に答える
0

java.lang.Object.wait()を使用するには、モニターを所有する必要があります。通常、同期ブロックによって行われます。

public void foo( Observer o ) throws InterruptedException
{
   Thread currentThread = Thread.currentThread();
   o.setThread( currentThread );
   synchronized( currentThread ) {
      currentThread.wait( 2000 );
   }
}

notify() の周りに同じメカニズムを追加します

public void update( Observable o ) throws InterruptedException {
   synchronized( currentThread ) {
      currentThread.notify();
   }

}

于 2013-04-08T19:06:37.460 に答える
0

同期を使用できます。currentThread.wait() を呼び出すと、スレッドはスリープ状態になり、モニター (currentThread) を解放します。このスレッドは、同じモニターで notify() を使用して別のスレッドによってウェイクアップされるのを待機します。

于 2013-04-08T19:25:21.283 に答える