0
System.out.println("Thread state: " + threads[i].getState());
threads[i].notify();

次の出力を生成します。

Thread state: WAITING
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at MyPakc.An.run(An.java:49)
at java.lang.Thread.run(Thread.java:679)

何が起こっている?スリープしているスレッドに通知できないのはなぜですか?

編集:threads []クラスのコード:

package Part2;

import java.util.List;
import javax.swing.JPanel;



class BThread extends Thread{
    private boolean completedThisIter = false;

    @Override
    public synchronized void run() {
        while (true) {
            completedThisIter = false;
            doStuff()
            System.out.println("Completed iter");
            completedThisIter = true;
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public boolean getCompletedThisIter() {
        return completedThisIter;
    }
}

編集:これを呼び出すコードは次のとおりです

public synchronized void run(){
// OTHER STUFF
    for (int iter = 0; iter < 1212; ++iter){
        System.out.println("Iter " + iter);
        lastAssignedBallIndex = -1;
        for (int i = 0; i < numThreads; i++) {
            //System.out.println("Num " + numThreads + "  " + i);
            //ballThreads[i] = new BallThread(ballList.subList(lastAssignedBallIndex+1,lastAssignedBallIndex+numBallsPerThread),
            //        ballPanel);
            //lastAssignedBallIndex += numBallsPerThread;
            System.out.println("State " + ballThreads[i].getState());
            if (ballThreads[i].getState() == Thread.State.NEW) {
                ballThreads[i].start();
            } else { //if (ballThreads[i].getState() == Thread.State.BLOCKED) {
                System.out.println("Thread state: " + ballThreads[i].getState());
                ballThreads[i].notify();
            }
        }
        //try{
            for (int i = 0; i < numThreads; i++) {
                while (!ballThreads[i].getCompletedThisIter()) {
                    System.out.println("iter:" + iter + " ball:" + i + "  " + ballThreads[i].getCompletedThisIter());
                    //wait(); // TODO elliminate polling here
                }
            }
            System.out.println("Joined");
        //}
       // catch(InterruptedException ie){ie.printStackTrace();}


        ballPanel.repaint();
        notifyAll();
        try{
            Thread.sleep(2);
        }
        catch (InterruptedException ie){}
    }
}
4

3 に答える 3

2

の状態を出力してから、ballThreads[i]に通知していthreads[i]ます。これが意図した動作かどうかはわかりませんが、オブジェクトのモニターを所有していない場合、スレッドに通知することは許可されていません。オブジェクトのsynchronized()ブロック内でこれを呼び出していますか?threads[i]


編集:

はい、このコードが取り出されるメソッドは同期されています

質問を編集した後synchronized、オブジェクトのモニターではなくメソッドにあるため、次のようなブロックにコードを配置する必要があります。

synchronized(threads[i]) {
    // some stuff
    threads[i].notify();
}

ここで (メソッド宣言のキーワードとは対照的に) 重要なのは、 Object で同期し、このブロック内でObjectsynchronizedを呼び出すことです。例:notify()

public void run()
{
    synchronized(myObject) {
        // do some stuff
        myObject.notify();
    }
}

また

public void run()
{
    synchronized(thread1) {
        // do some stuff
        thread1.notify();
    }
}

また

public void run()
{
    synchronized(syncObject) {
        // do some stuff
        syncObject.notify();
    }
}

パターンが見えますか?詳細はこちら: http://docs.oracle.com/javase/tutorial/essential/concurrency/locksync.html

于 2012-07-21T04:53:23.230 に答える
1

wait()また、notifiy()待機しているオブジェクトを同期する必要があります。wait()同期ブロックをロックするために使用したのと同じオブジェクトに対してandを実行するとnotify()、不正な監視状態の例外が取り除かれます

于 2012-07-21T04:55:52.430 に答える
1

wait/メカニズムの仕組みを完全に誤解していnotifyます。スレッドは、待機する必要があるものがあると判断する必要があります。次に、スレッドは を呼び出す必要がありますwait。それから何かが起こらなければなりません。notify次に、何かが起こったことをスレッドに伝えるために呼び出します。

wait待機する必要がある特定の何かがあることを最初に判断せずに、スレッドを呼び出すことはできません。notifyまた、スレッドに通知する必要がある何かがすでに発生するまで、呼び出すことはできません。発生したことは、待機することを決定したときにスレッドがチェックしていたことと同じである必要があります。

エラーが発生する理由は、待っていたものに関連付けられた同期が存在しないためです。これはwait/のセマンティクスに違反していnotifyます。

メールボックスが空でなくなるのを待っている場合は、メールボックスが空かどうかを確認し、空である場合は を呼び出す必要がありますwait。メールボックスの同期ルーチン内にいることを確認してください。そうしないと、メールボックスが (まだ) 空であることを知ることができません。次に、メールボックス (メールボックスの同期ルーチン内にある必要があります) に手紙を入れるときに、 を呼び出しnotifyて、待機中のスレッドにメールボックスの状態が変化したことを知らせます。メールボックスの状態など、スレッドがテストできる何かを待つ必要があります。

于 2012-07-21T05:22:44.890 に答える