0

フォーマットが悪いのでごめんなさい。私は自分のプログラムを書くためにメモ帳を使用しています。

これは機能するコードです。私が持っている唯一の質問は、通知と待機はSynchornizedブロックで使用する必要があることを読んだことです。ただし、次の例では、待機と通知は同期ブロックでは使用されず、エラーはスローされません。

class counthrd implements Runnable {

    Thread thrd;
    String x;
    counthrd cnt1;

    counthrd() {
    }
    boolean suspended;
    boolean stopped;

    counthrd(String s, counthrd cnt1) {
        thrd = new Thread(this, s);
        this.cnt1 = cnt1;
        thrd.start();
        x = s;
    }

    public void run() {

        try {
            System.out.println("Starting " + thrd.currentThread().getName());
            for (int i = 1; i < 100; i++) {
                System.out.print(i + "  ");
                if ((i % 10) == 0) {
                    System.out.println();
                    Thread.sleep(500);
                }
//synchronized(cnt1){
                while (suspended) {
                    System.out.println("going to wait mode");
                    wait();
                    notify();
                }
//}
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }

    synchronized void suspendme() {
        suspended = true;
        notify();
    }

    synchronized void resumeme() {
        suspended = false;
        notify();
    }
}

class counter {

    public static void main(String args[]) throws InterruptedException {
        counthrd cnt1 = new counthrd();
        counthrd cnthrd1 = new counthrd("thrd 1", cnt1);

        Thread.sleep(1000);
        System.out.println("going to wait mode");
        cnt1.suspendme();
        Thread.sleep(1000);
        System.out.println("resuming");
        cnt1.resumeme();
        Thread.sleep(1000);
    }
}
4

1 に答える 1

3

私のコメントを参照してください。IllegalMonitorStateExceptionスローされることはないのでwait、呼び出されることはありません。

counthrd...の2つのインスタンスがあることに注意してください。

counthrd cnt1 = new counthrd();
counthrd cnthrd1 = new counthrd("thrd 1", cnt1);

呼び出しているインスタンスsuspendmeresumemeオンになっているインスタンスを確認しますか?

Thread.sleep(1000);
System.out.println("going to wait mode");
cnt1.suspendme();
Thread.sleep(1000);
System.out.println("resuming");
cnt1.resumeme();
Thread.sleep(1000);

cnt1ここに見られるように、引数なしのコンストラクターを使用して初期化されます。

counthrd() {
}

重要なのは、cnt1実際に独自のスレッドを開始することは決してないということです。本当に何もしません。cnthrd1ここに見られるように、スレッドを開始するものです:

counthrd(String s, counthrd cnt1) {
    thrd = new Thread(this, s);
    this.cnt1 = cnt1;
    thrd.start();
    x = s;
}

重要なのは、それsuspendedはインスタンスフィールドであり、との間cnt1で共有されないということですcnthrd1。変更しても「待機モード」にcnt1.suspendedはなりません。が呼び出されることはないため、例外がスローされることはありません。cnthrd1wait

実演するために、代わりに、を呼び出しsuspendmeて試してみてください... :-)resumemecnthrd1

C:\dev\scrap>javac counter.java

C:\dev\scrap>java counter
Starting thrd 1
1  2  3  4  5  6  7  8  9  10
11  12  13  14  15  16  17  18  19  20
going to wait mode
going to wait mode
java.lang.IllegalMonitorStateException
resuming

そうは言っても、コードが実行すべきことを実行することをお勧めします。

  1. として宣言suspendedvolatileます。明示的なメモリオーダリングの保証がない場合、の更新された値を読み取るとき、または読み取る場合 でも、保証はありません。cnthrd1suspended
  2. cnt1フィールドとインスタンスを破棄します。それらの理由はありません。その空のコンストラクターも削除します。
  3. Thread.currentThread静的メソッドです。インスタンスを使用する必要はありません。それはさておき、ここでthrd等しいことが保証されてThread.currentThreadいます。
  4. counthrd.xに等しいthrd.getName; x代わりに使用しないのはなぜですか?
  5. より適切でわかりやすい名前を使用してください。たとえば、の代わりにx、なぜnameですか?の代わりにthrd、なぜthreadですか?の代わりにcounthrd、なぜCountingThreadですか?
  6. 呼び出す必要があるのはnotifyresumemeではなく、だけsuspendmeです。(実際、スレッドがスリープしている場合、つまり、呼び出しが誤ってトリガーnotifyされる可能性があります)suspendmeInterruptedException(i % 10) == 0
  7. notifyまた、while (suspended)ループに入れたくありません。whileこれで、ループを実際にステートメントに変えることもできますif
  8. synchronized (this)前に述べたように、を呼び出すコードを回避する必要がありますwhile
  9. コンストラクターで実際のロジックを実行することは避けてくださいthrd.start()
  10. suspendである必要はありませんsynchronizedresumeである必要もありませんsynchronizedwaitと呼び出しのみがnotifyそれを必要とします。

ここで、正しく機能する例の修正バージョンを見つけることができます。

于 2012-08-19T03:22:16.740 に答える