- PR -

スレッドの停止の仕方について

投稿者投稿内容
かずくん
ぬし
会議室デビュー日: 2003/01/08
投稿数: 759
お住まい・勤務地: 太陽系第三惑星
投稿日時: 2003-10-29 15:09
ほむらさんのサンプルに対するコメント。

いきなり、ThreadOnOff(false)が呼ばれた場合のために、
コード:
public void ThreadOnOff(...) {
    // ...
    else {
        if (null != t) {
            synchronized (t) {
               // ...
            }
        }
    }
}


とした方が良いように思えます。
# それとも、nullでmonitor握るのは、OKなのかな?
Keisuke
大ベテラン
会議室デビュー日: 2003/10/24
投稿数: 105
投稿日時: 2003-10-29 15:17
Keisuke です。

最初のコードから以下のようなものを想定してみました。
コード:
  class workerThread extends Thread {
    boolean bThreadAlive = false;
    public void run() {
      while (bThreadAlive == true) {
        // loop
      }
    }
  }
  volatile workerThread tobj = null;
  void startWorker() {
    if (tobj == null) {
      tobj = new workerThread();
    }
    tobj.bThreadAlive = true;
    tobj.start();
  }
  void stopWorker() {
    tobj.bThreadAlive = false;
    tobj = null;
  }


このコードでは stopWorkr の tobj.bThreadAlive = false の後で
スレッドスイッチが起こり、startWorker が呼ばれた場合に参照されない
スレッドが生き残ってしまいます。

実際には同期ブロックを使ってられるので、このような事は起きませんね。
ただ ThreadOnOff(true) の if( t != null ) ThreadOnOff( false );
の後に、別スレッドから又 ThreadOnOff(true) が呼ばれると同じような
スレッドが出来てしまいます。

スレッド競合によるバグは見つけ辛いので、危険の芽は早めに・・・

ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-10-29 17:27
ども、ほむらです。
-------
taka氏へ
引用:

 app.ThreadOnOff(true);
 app.ThreadOnOff(false);
 app.ThreadOnOff(true);
 app.ThreadOnOff(false);
とすると、"run()"メソッド内の"while( bThreadAlive == true ){"で
行われているフラグ判定が常にFalseとなりWhile文内へ処理が移る事はありません
でした。


そういうパターンもあるんですね(笑
t.start(); のあとに Thread.sleep(10); としても同じですかね。。。
あと、各スレットごとにインスタンスが異なるので
bThreadAlive=false;のあとtrueにすることは出来ません。(このつくり方ならばの話)
コンストラクタ以外でtrueにならないし
kill()以外でfalseにもならないことは
保証されています。
この作り方のミソはフラグがスレッドを実行するクラスのクラス変数であるということです。
なのでインスタンス単位で値の保証もされていると認識しています。

かずくん氏へ
ご指摘どおりですね^^;;
>if (null != t) {
で判定は必要です。。

修正個所は二つかな?
以下は修正後のThreadOnOff()です。
コード:

public void ThreadOnOff(boolean sw){
if( sw == true ){
try{
if( t != null ) ThreadOnOff( false );
synchronized(t){
t = new CMyThread((int)(Math.random() * 1000.0));
t.start();
Thread.sleep(10);
}
}
catch( InterruptedException ie){
}
}
else {
if( null != t ){
synchronized(t) {
t.kill();
t = null;
}
}
}
}



# Keisuke氏のいうパターンも当てはまる気がするので
# 誤字の修正と太字部分(synchronized)の追加。。
# もしかして僕宛の指摘だったのでしょうか?


[ メッセージ編集済み 編集者: ほむら 編集日時 2003-10-29 17:38 ]
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-10-29 17:45
ほむらです。
------
良く考えたらsleep()を使用すると環境依存っぽくなってしまうので
もう一つフラグを作ってrun()内部でwhile()の前にtrueに変更して
sleep()のかわりにこのフラグがtrueになるまで待つといった
形にしたほうが良いかもしれません。。。。
Wata
ぬし
会議室デビュー日: 2003/05/17
投稿数: 279
投稿日時: 2003-10-29 18:33
こんにちはWataです。スレッドが既にだいぶ進んでしまっていますが、以下について。
引用:

takaさんの書き込み (2003-10-29 13:53) より:
で、ではなぜ私の"run()"メソッドは"threadScroll.interrupt()"を発行すると
catchへ処理が移動するでしょうか?
たまたま、sleep()処理中だったからでしょうか?


試してみたところ、Threadがinterruptされてから、その後にsleepやwaitを
行うと、即時にInterruptedExceptionが発生するようでした。

したがってwhileでチェックしなくても、次のsleepまで停止が遅れるだけのようです。

ただし私の環境では、sleepの引数が0だとInterruptedExceptionが発生しませんでした。
taka
常連さん
会議室デビュー日: 2003/09/22
投稿数: 46
投稿日時: 2003-10-29 18:59
Wataさん、ご意見ありがとうございました。

>試してみたところ、Threadがinterruptされてから、その後にsleepやwaitを
>行うと、即時にInterruptedExceptionが発生するようでした。
私も確認できました。しかし、Wataさんがおっしゃったように
"Thread.isInterrupted()"をWhile文の中に付け加えるべきだと考えました。
見た目もロジックから意図が読めますしね。
ありがとうございました。
taka
常連さん
会議室デビュー日: 2003/09/22
投稿数: 46
投稿日時: 2003-10-30 08:31
ほむらさんのthreadOnOff()メソッドについて

threadOnOff(true)で処理される場合、"synchronized(t){"で
"NullPointerException"になりません?
ほむら
ぬし
会議室デビュー日: 2003/02/28
投稿数: 583
お住まい・勤務地: 東京都
投稿日時: 2003-10-30 09:54
ども、ほむらです。
taka氏へ
引用:

ほむらさんのthreadOnOff()メソッドについて

threadOnOff(true)で処理される場合、"synchronized(t){"で
"NullPointerException"になりません?


太字の部分ですよね。
ごめんなさい、実験してませんでした^^;;;
やってみたらご指摘のとおり例外が発生しました。

ところで、きのうふとおもったのですが
synchronized public void ThreadOnOff(boolean sw)
としてしまえば内部のsynchronize(t)の部分は不要になるのかなーと
思ってみました。。。
関数の性質上同期は必要ですしね。

スキルアップ/キャリアアップ(JOB@IT)