1
class myThreadRun implements Runnable
{

    public void run() {
        roo();
    }
    public synchronized void roo()
    {
        System.out.println("In thread before wait " + Thread.currentThread().getName());
        try {
            wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        JOptionPane.showMessageDialog(null, "After wait in\n"+Thread.currentThread().getName());
        System.out.println("In thread after wait " + Thread.currentThread().getName());
        //notify();
    }

    public synchronized void foo()
    {
        notify();
    }
}

public class ThreadingDemo {

    public synchronized void Start()
    {
        System.out.println("Labamba");
        myThreadRun mThRun =  new myThreadRun();
        Thread thread =  new Thread(mThRun);
        thread.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        //mThRun.foo(); //This works
        //mThRun.notify(); //crash
        //thread.notify();//crash
        try {
            thread.join();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
public static  void main(String[] args) {
        new ThreadingDemo().Start();
    }

これは、wait()とnotify()を示す単純なコードです。myThreadRunクラスでは、上記のコードに示されているように、run()メソッドはwait()を実行し、foo()メソッドはnotify()を実行します。 )プログラムはクラッシュしますが、mThRun.foo()は問題なく実行され、非常に必要な結果が得られます。理由を知る必要がありますか?

4

3 に答える 3

2

obj.wait()オブジェクトのモニターを allおよびに所有する必要がありますobj.notify()

そのため、synchronizedブロック内で呼び出されたときに機能しますmThRunが、外部では機能しません。mThRun.notify();したがって、を同期ブロックに入れると、次のように機能します。

synchronized (mThRun) {
    mThRun.notify();
}
于 2012-08-28T08:23:13.393 に答える
1

あなたの場合、IllegalMonitorStateExceptionが発生しています。

スレッドがオブジェクトのモニターで待機しようとしたことを示すため、または指定されたモニターを所有せずにオブジェクトのモニターで待機している他のスレッドに通知するためにスローされます。

言い換えれば、通知しようとしているオブジェクトのロックを保持していません。別のオブジェクトをロックしても効果はありません。


notify()とwait()を使用する場合は、状態を変更して確認する必要があります。これを行わない場合は、次のいずれかを見つけることができます

  • notify()はwait()の前に呼び出され、シグナルが失われます
  • wait()は時期尚早に目覚めます

通知/待機が信頼できるメッセージングプロトコルであると想定することはできません。

ほとんどの場合、Java 5.0(2004)からのより良い選択である並行性ライブラリの使用を検討することをお勧めします。

于 2012-08-28T08:26:06.383 に答える
0

待機/通知で非常に苦労している可能性があります。とてもシンプルです。知っておく必要があるのは、モニター ロックに使用されるオブジェクトです。同じコードを機能させるために、同じコードを変更しました: (コードを変更した場所に MAK コメントを入れました。役に立てば幸いです)

class MyThreadRun implements Runnable {
    public void run() {
        roo();
    }
    public synchronized void roo() {
        System.out.println("In thread before wait " + this);
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        JOptionPane.showMessageDialog(null, "After wait in\n" + Thread.currentThread().getName());
        System.out.println("In thread after wait " + Thread.currentThread().getName());
    }

}

public class ThreadingDemo {

    public static void main(String[] args) {
        MyThreadRun mThRun = new MyThreadRun();
        System.out.println("Labamba: " +mThRun);
        Thread thread = new Thread(mThRun);
        thread.start();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        //mThRun.foo(); //This works  //MAK: no sense
        //mThRun.notify(); //crash   //MAK: Need monitor lock
        synchronized (mThRun) {
            mThRun.notify();//crash                  //MAK: will work now
        }
        try {
            thread.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
于 2013-11-28T13:42:26.803 に答える