4

私は2つのスレッドを構築しようとしています。スレッドAはメインスレッド、スレッドBは2番目のスレッド、スレッドBは時間のかかる関数を介して変数を更新しています(最終的にスレッドAは使用する必要があるため、この変数は両方のスレッド間で共有する必要があります)その変数も同様です)が、スレッドBの完了に時間がかかりすぎる場合(例外を使用)、スレッドAがスレッドBを終了するようにします。

私が試したのは次のとおりです。

Thread thread = new Thread() {
     public void run() {
         /// run something that could take a long time
     }
};

synchronized (thread) {
    thread.start();
}

System.err.println("Waiting for thread and terminating it if it did not stop.");
try {
   thread.wait(10000);
} catch (InterruptedException e) {
   System.err.println("interrupted.");
}

それが10秒以上実行された場合に動作を終了するという期待される動作を与える必要がありますか?スレッドを実行するメソッドが戻るため、スレッドオブジェクトは待機後に削除されます。

現在、このコードで何が起こるかというと、wait(10000)コマンドで常にjava.lang.IllegalMonitorStateExceptionが発生します。

4

2 に答える 2

3

自分がいないオブジェクトをIllegalMonitorStateException呼び出している場合は、常にを取得します。wait()synchronized

try {
    // you need this to do the wait
    synchronized (thread) {
       thread.wait(10000);
    }
} catch (InterruptedException e) {
    System.err.println("interrupted.");
}

が終了するのを待っている場合は、threadおそらく次のことを実行しようとしています。

try {
    thread.join(10000);
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
    System.err.println("interrupted.");
}

残念ながら、その時点ではスレッドが実行されているかどうかはわかりjoinません。タイムアウトした(不平を言う)かどうかが返されないためです。したがってthread.isAlive()、参加後かどうかをテストする必要があります。

threadミリ秒より長く実行された場合にキャンセルする方法を尋ねている場合は10000、を使用するのが正しい方法thread.interrupt()です。これにより、sleep()またはwait()メソッドがをスローInterruptedExceptionし、スレッドに割り込みフラグを設定します。

割り込みフラグを使用するには、スレッドは次のようなことをしている必要があります。

   while (!Thread.currentThread.isInterrupted()) {
       // do it's thread stuff
   }

InterruptedExceptionまた、がスローされると割り込みフラグがクリアされるため、次のようなことを行うのは常に良いパターンです。

} catch (InterruptedException e) {
    // set the interrupt flag again because InterruptedException clears it
    Thread.currentThread.interrupt();
    System.err.println("interrupted.");
}
于 2012-04-28T00:12:41.173 に答える
1

そのコードは正しくありません。メソッドwaitはクラスで宣言されObjectており、呼び出されたオブジェクトのモニターインスタンスとして使用して現在のスレッドを一時停止することを目的としています。このメソッドはsynchronizedセクションでのみ呼び出すことができます。そのため、例外が発生します。

あなたの問題に関して:一般的に、それが停止したくない場合、あなたは別のスレッドを停止することはできません。したがってThread.interrupt、スレッドが機能を停止する必要があることをスレッドに通知するために呼び出す必要があり、その通知を考慮するかどうかを決定するのはそのスレッド次第です。スレッドが中断されているかどうかを確認するには、interrupted()またはisInterrupted()メソッドを使用できます。

于 2012-04-28T00:14:21.063 に答える