- ベストアンサー
スレッドの停止方法についての質問
- スレッドの停止方法についての質問
- スレッドの停止方法に関して、volatileキーワードの必要性について疑問があります。
- 質問者は、インターネットで類似のコードを検索しても、volatileキーワードが欠けているものが多く見つかるため、自身のコードにもvolatileキーワードを追加した方が良いのか悩んでいます。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
terminate() が他のスレッドから呼び出されるとしたら、確かに volatile は必要ですね。(もしくは synchronized で同期化するか) また、volatile による性能低下ですが、おそらくスレッド停止のコストの方が桁違いに大きいので考える必要は無いと思います。 ただし、特に理由が無いのであれば、停止処理には interrupt を使うのが無難でしょう。 http://www.ibm.com/developerworks/jp/java/library/j-jtp05236/#c マルチスレッドプログラミングについては、下記の本がとても参考になりますよ。 ■ Java並行処理プログラミング http://www.amazon.co.jp/dp/4797337206
その他の回答 (2)
- root139
- ベストアンサー率60% (488/809)
> InterruptedException を catch で握りつぶして処理を続けるような処理パターンだと、止まらなくなってしまうのです。 ああ、なるほど、そういったケースのご懸念でしたか。 これも「Java並行処理プログラミング」に出ていたイディオムですが、InterruptedException が発生しても処理を続ける場合には catch 節を空にせず、 Thread.currentThread().interrupt() でインタラプトステータスを復元するというものがあります。 } catch (InterruptedException ex) { Thread.currentThread().interrupt(); // 処理は続行されるがステータスは立つ } これを習慣にしてしまえば、止まらなくなるような事は無なくなるかと。 まあ、フラグを併用するのが悪いわけではないのですが、私の場合、マルチスレッド環境下では変化する状態を少しでも減らしたいので、なるべくインタラプテッドステータスのみで済ましてますね。
- root139
- ベストアンサー率60% (488/809)
> 誤りがコピーされて拡大再生産されているだけなんでしょうか? おそらく、そうだと思います。 volatile が無くても正常に動作することも多いですから、テストで検出するのも難しいですし。 書籍でも間違っているものも有るようですよ。 先の回答にも書いた「Java並行処理プログラミング」でも同じようなキャンセル処理の例がありますが、しっかり volatile が付いていて、確実な動作にはそれが必要な旨が書いてあります。 それから、インタラプトについてですが、ブロッキングメソッドを使っていなくてもインタラプトは検出できます。 インタラプトされた時点で sleep や wait の最中であれば InterruptedException が発生しますが、それ以外であれば Thread.isInterrupted() や Thread.interrupted() で true が返るようになります。 http://java.sun.com/javase/ja/6/docs/ja/api/java/lang/Thread.html#isInterrupted%28%29 ご質問のコードで言えば、 done の代わりに Thread.currentThread().isInterrupted() を使うことができ、そうすれば他のクラスから直接 MyThread.interrupt() を呼び出しても動作する様になります。 while (!done) { ↓↓↓↓↓↓↓ while (!Thread.currentThread().isInterrupted()) { 先にご紹介した↓でもこのような方式を使っています。 http://www.ibm.com/developerworks/jp/java/library/j-jtp05236/#c
補足
ご回答ありがとうございます。やはり、誤りが広く世間に蔓延しているのですね。 SUNなどの権威あるサイトでは volatile が入っているようです。 >インタラプトについてですが、ブロッキングメソッドを使っていなくてもインタラプトは検出できます はい、確かにそうで、気をつけて使えば問題ないのですが、 sleepや waitがInterruptedExceptionを挙げた時点でインタラプトフラグが落ちてしまうことが微妙な 問題を起こすことが有ります。 run() のループ内で ブロックは解除したいがループの後続の処理をやりたいがために InterruptedException を catch で握りつぶして処理を続けるような処理パターンだと、 止まらなくなってしまうのです。 #このパターンも広く蔓延していて、私もよく使います。 で、面倒なので、フラグを併用する今のパターンに落ち着いています。
補足
解答ありがとうございました。やはり volatile はいるのかな? インターネット上のサンプルソースの 99% は volatile も synchrinized も無しなのでひょっとしたらと思っていたのですが、 誤りがコピーされて拡大再生産されているだけなんでしょうか? インタラプトの件ですが、スレッドのメインループでブロッキング メソッドを使うとは限らないので、フラグ方式とインタラプトを 併用して安全を図っています。