Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

スレッド呼び出し元の状態取得

子スレッドの終了を待って処理を再開する場合、join()を使用すれば良いですが、その逆に子スレッドにおいて呼び出し元のメソッドの終了を待ってから処理を再開する方法はありますでしょうか。

子スレッドから呼び出し元の状態を取得できれば、無限ループの中から定期的に状態を参照し、メソッド終了を確認できたときにループを抜けて処理を再開できるのではと考えています。子スレッドから呼び出し元メソッドの終了を知る手段が知りたいです。

12

回答

5972

閲覧

12件の回答

評価

0

子が親の状態を参照するのではなく
親から子へ処理の再開を通知させて
あげればいいと思います。

class MyThread extends Thread{
  private boolean stop = true;

  public void run(){
    //前処理

    //親からの通知を待つ
    while(stop){}

    //後処理
  }

  public void restart(){ stop = false; }
}

評価

0

stc さんサンプルプログラムまでありがとうございます。
親側から通知する場合、以下のような順序になるかと思います。

(1)親:子スレッド生成
(2)子:自処理開始
(3)子:待機(無限ループで再開通知待ち)
(4)親:子へ終了通知
(5)子:終了通知を受けて自処理を再開
(6)親:自処理を終了

ここで(5)と(6)を見ると、子は親の終了を待たずに処理を再開してしまいます。(5)のなかで少しだけ sleep させて(6)を待つという方法も考えましたが、なんかスマートじゃないですよね。
なので、次のようにできないかと考えています。

(1)親:子スレッド生成
(2)子:自処理開始
(3)子:待機(無限ループで親スレッド監視)
(4)親:自処理を終了
(5)子:親スレッドの終了を検出
(6)子:自処理を再開

こうすることで、(4)の後に(6)という順序性が保たれると考えましたが、(3)の親スレッド監視の方法が見つかっていません


#卵が先か鶏が先か・・・
#リフレクション等で検索していますが、解決策を見つけられません。
#何か適当なデザインパターンがあればいいのですが・・・

評価

0

見当違いならすみません。
子へ終了通知をどのように行っているかわかりませんが、単純に終了処理を呼び出すメソッドの返却値を返すようにすればいいのではないですか?

評価

0

> (4)親:子へ終了通知
> (5)子:終了通知を受けて自処理を再開
> (6)親:自処理を終了

順番がおかしいです。
親の処理を終了してから子へ終了通知を出します。
(4)親:自処理を終了
(5)親:子へ終了通知
(6)子:終了通知を受けて自処理を再開

>(2008-11-08 00:45)
> 呼び出し元のメソッドの終了を待ってから処理を再開する

>(2008-11-08 08:27)
> (5)子:親スレッドの終了を検出

初めは「メソッドの終了」ということでしたので
親のメソッド終了時もしくは終了後に通知すれば
いいと思ったのですが、それでは不十分という
ことでしょうか。

呼び出し元のスレッド終了後に処理を再開したい
のであれば、以下のようにすればできます。
(java1.5以降)

class MyThread extends Thread{
  Thread th = null;

  public MyThread(Thread th){
    this.th = th;
  }

  public void run(){
    //前処理

    //親のスレッド終了を待ちます
    while(!(th.getState()==Thread.State.TERMINATED)){}

  //後処理
  }
}

評価

0

> while(!(th.getState()==Thread.State.TERMINATED)){}

単に th.join() でいいかもしれませんね。

評価

0

stc さん、cova さん、ご回答ありがとうございます。

すみません、「親スレッド」という表現は誤りでした。
(4)親:自処理を終了
というのは、スレッドを呼び出したメソッドを return した後という意味で、その後にスレッド側の処理を再開したいのです。

以下イメージです。

class Oya{

  public static void main(String[] args) {

    myThread = new MyThread();
    myThread.start();

    // 親側の処理

    return;
  }

}

class MyThread extends Thread{

  public void run(){
    // 前処理

    // 親のメソッド終了監視
    while(★Oya#root()が return していない){}

    // 後処理
  }
}


Oya#root() を return した後に Oya#root() 側で処理を続ける(何かしらの方法で、スレッド側に Oya#root() の終了を通知する)ということは不可能なので、Oya#root() の外部から Oya#root() の終了(return したということ)を知りたいという質問です。
MyThread#run() の★の部分の条件の書き方がわかりません。
こんなこと不可能でしょうか?

評価

0

Oya#main(String[]) で return すると
Oyaを処理しているスレッドが終了すると
思いますので、Oyaを処理しているスレッドを
myThread に渡して、myThread内で join すれば
いいと思います。

イメージと実際とは違って return の先がある
場合は、そのreturn先で myTread に通知する
ことになると思います。

評価

0

親にステータス(Oya#root()が return していないかどうかをあらわすもの)を設定して、そいつを子から参照するようにすればいいと思います。

評価

0

2008-11-08 19:27の書き込みは、嘘です。(削除したいなー)

stcさんの方法がいいと思います。

評価

0

# 前記プログラムイメージの Oya#root() は、Oya#main() の誤記でした。

Oya クラスは Tread クラスを継承していないので、Object オブジェクトをスレッドに渡して、どうにかできないか考えてみようと思います。

評価

0

> Oya クラスは Tread クラスを継承していないので

Thread#currentThread() が使えないでしょうか。

評価

0

stc さん。

Thread#currentThread() を使用して、目的を達成することができました。
Thread クラスを継承していなくても、Thread オブジェクト取得できるんですね。
ありがとうございました。

今後、同じところで悩む人がいるかもしれないので、
サンプルコードを掲示しておきます。

----
public class Oya{
  public static void main(String[] args){

    System.out.println("[START] Oya#main()");
    Thread thread = Thread.currentThread();
    Ko ko = new Ko(thread);

    ko.start();
    
    try{
      Thread.sleep(5000);
    }
    catch(Exception e){
    }
    
    System.out.println("[END] Oya#main()");
    return;
  }
}

public class Ko extends Thread{
  Thread threadOya = null;

  public Ko(Thread threadOya) {
    this.threadOya = threadOya;
  }

  public void run() {
    System.out.println("[START] Ko#run()");
    try{  
      threadOya.join();
    }
    catch(Exception e){
    }
    System.out.println("[END] Ko#run()");
    return;
  }
}

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。