Java非推奨スレッド・プリミティブ機械翻訳についてJava非推奨スレッド・プリミティブThread.stopが非推奨なのはなぜですか本質的に安全ではないからです。スレッドを停止すると、そのスレッドがロックしたすべてのモニターのロックが解除されます。(ThreadDeath例外がスタックまで伝わると、モニターのロックが解除される。これらのモニターによって以前保護されていたオブジェクトが整合性のない状態になると、ほかのスレッドも、これらのオブジェクトが整合性のない状態にあるとみなします。そのようなオブジェクトは、壊れたオブジェクトと呼ばれます。壊れたオブジェクトに対してスレッドが操作を実行すると、予期しない結果になる可能性があります。この動作は、微妙で検出が困難な場合と、はっきりと通知される場合があります。ほかの非チェック例外とは異なり、ThreadDeathは、スレッドをそのまま強制的に終了します。このため、ユーザーは、プログラムが壊れる可能性を警告されることがありません。プログラムが壊れていることは、実際に損傷を受けたしばらくあとに明らかになり、それが数時間後または数日後になることもあります。ThreadDeath例外をキャッチし、壊れたオブジェクトを修復することはできないのですか理論的には、おそらく可能です。正しいマルチスレッド・コードを記述するのは非常に複雑なタスクです。これがほとんど実行不可能なタスクであることは、次の2つの理由によります。スレッドは、ThreadDeath例外をほとんどすべての場所でスローする。このことを念頭に置いて、すべての同期化されたメソッドおよびブロックを詳細に調査する必要がある。スレッドは、1番目の例外のクリーンアップ中(catchまたはfinally節)に、2番目のThreadDeathをスローすることがある。クリーンアップは成功するまで繰り返さなければならないでしょう。この動作を確実に行うコードは非常に複雑になる。したがって、この処理は現実的ではありません。Thread.stopの代わりに何を使うべきですか多くの場合、ターゲット・スレッドの実行停止を指示するには、stopではなく、単に一部の変数を変更するコードを使用する必要があります。ターゲット・スレッドは、この変数を定期的に検査し、実行を停止するべきことを変数が示している場合には、スレッドのrunメソッドから通常の方法で復帰する必要があります。停止要求の即時通信を確実にするには、変数をvolatileにする(または、変数へのアクセスを同期化する)必要があります。アプレットに次のstart、stop、およびrunメソッドが含まれているとします。}アプレットのstopおよびrunメソッドを次のコードと置き換えることによりThread.stopを使用せずに済みます。}長い間(入力などを)待機しているスレッドをどうすれば停止できますかその目的には、Thread.interruptを使用します。null)のあとに、Thread.interruptを呼び出して待機状態に割り込むことができます。}この方法では、割込み例外をキャッチするがそれを処理する準備のできていないメソッドはその例外をただちに再宣言することが重要です。ここで再スローではなく再宣言と書いたのは、例外をいつも再スローできるとはかぎらないからです。InterruptedExceptionをキャッチしたメソッドが、この(確認済みの)例外をスローするように宣言されていない場合は、次のような決まった書き方により自らに再割り込みする必要があります。Thread.currentThread().interrupt();これにより、スレッドは、可能なかぎり早くInterruptedExceptionを再発行できるようになります。スレッドがThread.interruptに応答しないとどうなりますかアプリケーション独自の技法が使用可能な場合もあります。スレッドが既知のソケット上で待機している場合は、ソケットを閉じることによりスレッドをただちに復帰させることができます。残念ながら、汎用的に使用できる技法はありません。待機しているスレッドがThread.interruptに応答しないすべての状況では、そのスレッドはThread.stopにも応答しないことに注意してください。そのような状況としては、意図的なサービス妨害攻撃や、thread.stopとthread.interruptが適切に機能しない入出力操作などがあります。Thread.suspendおよびThread.resumeが非推奨なのはなぜですかThread.suspendは、本質的にデッドロックを起こす傾向があります。ターゲット・スレッドが、中断される時点で、重要なシステム・リソースを保護するモニターをロックしている場合、ターゲット・スレッドが再開されるまでどのスレッドもそのリソースにアクセスできません。このとき、ターゲット・スレッドを再開するスレッドが、resumeを呼び出す前にこのモニターをロックしようとすると、デッドロックが発生します。通常、このようなデッドロックは、プロセスの凍結により明らかになります。Thread.suspendとThread.resumeの代わりに何を使うべきですかThread.stopの場合と同様、賢明なアプローチは、スレッドの望ましい状態(実行中または中断中)を示す変数をターゲット・スレッドにポーリングさせることです。望ましい状態が中断中である場合、スレッドはObject.waitを使用して待機します。スレッドが再開されたときは、ターゲット・スレッドはObject.notifyを使って通知を受けます。アプレットに次のようなmousePressedイベント・ハンドラが含まれており、それがblinkerというスレッドの状態を切り替えるとします。}上のイベント・ハンドラを次のコードで置き換えると、Thread.suspendおよびThread.resumeを使わなくて済みます。}そして次のコードを実行ループに追加します。catch節の内部に置く必要があります。このメソッドをsleepと同じ節に入れると効果的です。チェックはsleepの前ではなくあとに行われるので、スレッドが再開されるとただちにウィンドウが再描画されます。このように記述したrunメソッドは、次のようになります。}mousePressedメソッドのnotifyおよびrunメソッドのwaitは、synchronizedブロックの内部にあることに注目してください。これは言語の文法で要求されているからだけでなく、waitおよびnotifyが適切に直列化されることを保証します。この場合は、これにより競合状態が回避されます。中断されたスレッドがnotifyを検出できずに、ずっと中断されたままになる事態を避けられます。Javaにおいて同期化に要するコストは、プラットフォームが成熟するにつれて減少していますが、まったくなくなることはありません。簡単な技法を使用して、上の実行ループの反復処理に追加した同期処理を省くことができます。追加された同期ブロックは、スレッドが実際に中断されている場合にのみ同期ブロックを入力する、わずかに複雑なコードに置き換えられます。}明示的な同期化を行わない場合は、threadSuspendedをvolatileに設定して、一時停止要求の通信がすみやかに行われるようにしてください。結果のrunメソッドは次のようになります。}今までの2つの手法を組み合わせれば、安全に停止または中断させることのできるスレッドを生成できますかはい、かなり簡単に生成できます。1つだけ問題になるのは、別のスレッドがターゲット・スレッドを停止させようとする時点で、ターゲット・スレッドがすでに中断されている可能性があるという点です。stopメソッドが状態変数(blinker)をnullに設定するだけであれば、ターゲット・スレッドは終了(本来の動作)せずに、中断されたまま(モニターを待機した状態)になります。アプレットが再起動されると、複数のスレッドが同時にモニターを待機した状態で終了するため、動作が異常になります。この状況を正すには、stopメソッドで、ターゲット・スレッドが中断されている場合に、そのスレッドをただちに再開する処理を確実に実行しなければなりません。ターゲット・スレッドは、再開したのち、自身が停止されたことをただちに認識して、適切な方法で終了しなければなりません。そのような処理を加えたrunおよびstopメソッドは、次のようになります。}stopメソッドでThread.interruptを呼び出す場合(以前に説明した方法)は、notifyを呼び出す必要はありませんが、同期化は行う必要があります。それにより、競合状態のためにターゲット・スレッドが割込みを検出し損ねることを防げます。このページのスクリプトはWebページのトラフィックを追跡するものであり、内容は変更されません。