- - PR -
スレッドの停止の仕方について
| 投稿者 | 投稿内容 | ||||||||
|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-10-29 04:16
> このやりかた(threadScroll = null)でスレッドを止めることができるとは、
> 意外でした。私は今まで見たことがありませんでした。 (threadScroll = null)がスレッドを止めるのではなく、 (threadScroll = null)により、 run メソッドから抜けることで スレッドが終了します。 Threadクラスの説明に(スレッドが終了するのは)、 「run メソッドの呼び出しから復帰することによって、または run メソッド以外から送られる例外をスローすることによって、デーモンスレッドではないすべてのスレッドが終了した場合 」とあります。 | ||||||||
|
投稿日時: 2003-10-29 08:38
かずくんさん、Kissingerさん、unibonさん、Keisukeさん、ご意見ありがとうございました。
まず、かずくんさんから教えていただいたサイトを拝見させていただきました。その中で、 >whileループの中でsleep(巨大な数)などとしていると、 なかなかbreak文に到達できず >に、 いつまでたってもスレッドが停止しないということになりかねません。 >こういうときは、Threadオブジェクトのinterruptメソッドを呼べば、 >InterruptedExceptionが強制的に発生し、sleepの待ちが解消されて、 スレッドを終了する >ことができます。 とされていました。私の場合、whileループの中でsleep(巨大な数)をしているわけではありませんが、スレッドの開始/停止フラグチェックの前後に多少時間がかかる処理があるのでやはり "InterruptedExceptionの強制的発生"を行うのが妥当でしょうか。 Kissingerさんのご意見では、 >threadへの interruptは、割込んだことを記憶させることができますが、 >現在の処理を直ちに終了させるかどうかは、処理系に依存します。 >どうかそのような違いに依存しない設計をして下さい。 うーん、確かにそうなのでしょうね・・・ しかしかずくんさんから教えていただいたサイトの例(whileループの中でsleep(巨大な数)) の場合、このような止め方しかないような気がします・・・ unibonさんのご意見、 >このやりかた(threadScroll = null)でスレッドを止めることができるとは、 >意外でした。私は今まで見たことがありませんでした。 すみません、これは私の説明不足です。Keisukeさんからもご説明ありましたが、 runメソッド内で(threadScroll = null)を確認しているWhile文がありそこでWhile文から 抜け、runメソッドから抜けるといった意味です。 Keisukeのご意見 >素直に、下記のようにするのがよいのでは。 教えていただいたサイト、拝見しました。 いくつか、スレッドの止め方があった為、Keisukeさんの言わんとしている事を私が理解できたかはわかりませんが、気になる方法として下記の文がありました。 しかし、この文でも例えばstop()メソッド発行後、直にstart()メソッドを発行すると runメソッド内部の"while (blinker == thisThread)"判定前に、blinkerがNullではなくなりスレッドが停止しないという事は考えられないでしょうか? private volatile Thread blinker; public void start() { blinker = new Thread(this); blinker.start(); } public void stop() { blinker = null; } public void run() { Thread thisThread = Thread.currentThread(); while (blinker == thisThread) { try { thisThread.sleep(interval); } catch (InterruptedException e){ } repaint(); } } /********************************************************/ 私の見解としては、スレッド内部のWhile文なり、If文なりでスレッドの停止確認を行っていて、その判定までに時間のかかる処理(sleep(大きな数))などが行われている場合はinterruptを使うと考えました。 | ||||||||
|
投稿日時: 2003-10-29 09:47
こんにちは、Wataです。
blinkerには常に最新のスレッドが格納されるため、既に最新でなくなった スレッドによるwhile (blinker == thisThread)の判定はfalseになります。 ただし、厳密にはblinkerのアクセスに同期が必要です。 Effective Javaで紹介されているスレッド終了の例を以下に紹介します。
また、最初に示されたInterruptedExceptionによるループ脱出の例は sleep中以外にthreadScroll.interrupt()の呼び出しを行った場合、スレッドが 停止せず、threadOnOffメソッドも復帰しなくなるのではないでしょうか? whileの判定にThread.interrupted()が必要だと思います。 あと、threadOnOff(true)が続けて呼び出された場合にスレッドが複数起動してしまいます。 [ メッセージ編集済み 編集者: Wata 編集日時 2003-10-29 09:49 ] | ||||||||
|
投稿日時: 2003-10-29 11:48
Wataさん、ご意見ありがとうございました。
>blinkerには常に最新のスレッドが格納されるため なるほど、わかりました。 この方法だったら、start()メソッドを連続して2回発行しても古いほうのスレッドは 停止しますね。 >最初に示されたInterruptedExceptionによるループ脱出の例は >sleep中以外にthreadScroll.interrupt()の呼び出しを行った場合、スレッドが >停止せず、threadOnOffメソッドも復帰しなくなるのではないでしょうか? threadScroll.interrupt()を発行すると、run()メソッドのtry...catch処理が catch文へ移るのでスレッドが終了します。 かずくんさんから教えていただいたサイトにも同様のケースが書かれておりました。 Wataさんのご質問を理解していなかったらすみません・・ | ||||||||
|
投稿日時: 2003-10-29 12:54
InterruptedExceptionをキャッチする必要があるメソッドは ・Thread.sleep() ・Thread.join() ・Object#wait() と内部的にこれらを使用する他のメソッドなどです。 つまり、これらのメソッドの実行中しかInterruptedExceptionは発生しませんし、 キャッチすることはできません。 その他の場合は、主にスレッドに割り込みステータスが設定されて、Thread.isInterrupted() の値がtureになります。 Thread.interrupt()のAPIを確認してみてください。 | ||||||||
|
投稿日時: 2003-10-29 13:53
Wataさん、再度のご意見ありがとうございました。
>InterruptedExceptionをキャッチする必要があるメソッドは >・Thread.sleep() >・Thread.join() >・Object#wait() >と内部的にこれらを使用する他のメソッドなどです。 >つまり、これらのメソッドの実行中しかInterruptedExceptionは発生しませんし、 >キャッチすることはできません。 >Thread.interrupt()のAPIを確認してみてください。 で、"Thread.interrupt()のAPI"を読んで見ると >Object クラスの wait()、wait(long)、wait(long, int) メソッドの呼び出し、 >またはこのクラスの join(), join(long)、join(long, int)、sleep(long)、 >または sleep(long, int) メソッドの呼び出しでこのスレッドがブロックされる場合、 >割り込みステータスはクリアされ、InterruptedException を受け取ります。 との事でした。 で、ではなぜ私の"run()"メソッドは"threadScroll.interrupt()"を発行すると catchへ処理が移動するでしょうか? たまたま、sleep()処理中だったからでしょうか? | ||||||||
|
投稿日時: 2003-10-29 14:00
ども、ほむらです。
今のところ僕の場合特に問題なかったのですが。。。。 どういった場合に問題が出そうですか? こんどは省略ナシの形でコード貼り付けます。。。 #紹介されているURLはこれから目を通します^^;;;;
| ||||||||
|
投稿日時: 2003-10-29 15:08
ほむらさん、ご意見とフルロジックをありがとうございました。
ほむらさんからいただいたロジックを試してみました。 ただ、"public static void main(String [] argv){"の中で app.ThreadOnOff(true); Thread.sleep(1020); app.ThreadOnOff(false); app.ThreadOnOff(true); Thread.sleep(520); app.ThreadOnOff(false); とされていますが、これを app.ThreadOnOff(true); app.ThreadOnOff(false); app.ThreadOnOff(true); app.ThreadOnOff(false); とすると、"run()"メソッド内の"while( bThreadAlive == true ){"で 行われているフラグ判定が常にFalseとなりWhile文内へ処理が移る事はありません でした。 そりゃそうだよ!"app.ThreadOnOff(true);"の後にすぐ"app.ThreadOnOff(false);" してんだから! と言われるかもしれませんが・・・ これって、"class CMyThread"で"bThreadAlive = true;"とされ実際にスレッドが走るまでに "bThreadAlive = false;"されてしまっているという事ですよね? だとしたら、この逆で"bThreadAlive = false;"したのにスレッド内While判定文までに "bThreadAlive = true;"と設定されたらスレッドは止まらないとはなりませんか? | ||||||||
