人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Javaのスレッドについての質問です。

以下のようにfor文でスレッドを4つ立ち上げるプログラムを組みました。

for( int i = 0; i < 4; i++ ) {

//メッセージを送るスレッドをたてる
Fieldmsg fieldmsg = new Fieldmsg(socket);
fieldmsg.start();
fieldmsg.join();

}

fieldmsg.join(); が食い止めているので、この場合は1つのスレッドが終わるまで
次のスレッドは立ち上がらないと思います。

問題は、4つのスレッドすべてが立ち上がり、4つが終了するのを見届けたい場合です。

Fieldmsg fieldmsg;

for( int i = 0; i < 4; i++ ) {

//メッセージを送るスレッドをたてる
fieldmsg = new Fieldmsg(socket);
fieldmsg.start();

}

fieldmsg.join();

こうしたらどうなるでしょうか?

それとも4つのスレッド全部にフラグを立てるような仕組みをいれてそれを監視するという方法がいいのでしょうか?

●質問者: zachouR
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● Sampo
●50ポイント

4つのスレッドすべてが終了するまで待つのに
fieldmsg.join();
ではいけません。
なぜなら、fieldmsg が指しているのは最後に作ったスレッドだけだからです。

List<Fieldmsg> fieldmsgs = new ArrayList<Fieldmsg>();

for( int i = 0; i < 4; i++ ) {

  //メッセージを送るスレッドをたてる
  Fieldmsg fieldmsg = new Fieldmsg(socket);
  fieldmsg.start();

 // 終了監視用のリストに今立てたスレッドを格納
  fieldmsgs.add(fieldmsg);
}

// すべてのスレッドの終了を監視
for (Fieldmsg fieldmsg : fieldmsgs) {
 fieldmsg.join();
}

4つ作るなら4つともスレッドへの参照を取っておいて、すべてについて終了を待ってあげる必要があります。


zachouRさんのコメント
わざわざ、ありがとうございます!大変参考になりました! さっそく組み込みました!

2 ● a-kuma3
●50ポイント

Thread#join() をスレッドの数だけ呼ぶ必要がある、というのは既に出てるので、別の方法を。
java.util.concurrent パッケージのクラスを使うと、もう少し簡単になります。
CountDownLatch が良いのかな...

public class Hatena {

 static class MyThread extends Thread {
 private CountDownLatch latch_;
 private String answer_;
 private int no_;
 MyThread(int no, latch) {
 no_ = no;
 latch_ = latch;
 }
 public void run() {
 try {
 Thread.sleep((int)(Math.random() * 10000));
 } catch (InterruptedException e) {
 System.out.println(e);
 }
 answer_ = "hatena-" + no_;
 System.out.println("finish No." + no_);

 // カウントを一つ減らす
 latch_.countDown();
 }
 public String getAnswer() {
 return answer_;
 }
 }

 public static void main(String[] args) {
 try {
 CountDownLatch latch = new CountDownLatch(4);
 for (int i = 0 ; i < 4 ; ++i) {
 MyThread th = new MyThread(i, latch);
 // 四回スタート
 th.start();
 }

 // カウントがゼロになるまで待つ
 latch.await();

 System.out.println("All Finish !!!");

 /*
 む、結果を取るには Thread を保存しておかなきゃ駄目か...
 */

 } catch (InterruptedException e) {
 System.out.println(e);
 }

 }
}



追記です。


スレッドに CountDownLatch を渡してるなら、結果も入れ物を渡して、スレッドに詰めてもらう方がすっきりするような気がします。
入れ物は何でも良いんですけど、例えば、java.util.concurrent.SynchronousQueue 。

public class Hatena {

 static class MyThread extends Thread {
 private CountDownLatch latch_;
 private SynchronousQueue<String> result_;
 private int no_;
 MyThread(int no, latch, result) {
 no_ = no;
 latch_ = latch;
 result_ = result;
 }
 public void run() {
 try {
 Thread.sleep((int)(Math.random() * 10000));
 String answer = "hatena-" + no_;
 result_.put(answer);
 } catch (InterruptedException e) {
 System.out.println(e);
 }

 System.out.println("finish No." + no_);

 // カウントを一つ減らす
 latch_.countDown();
 }
 public String getAnswer() {
 return answer_;
 }
 }

 public static void main(String[] args) {
 try {
 CountDownLatch latch = new CountDownLatch(4);
 SynchronousQueue<String> result = new SynchronousQueue<String>();
 for (int i = 0 ; i < 4 ; ++i) {
 MyThread th = new MyThread(i, latch, result);
 // 四回スタート
 th.start();
 }
 // カウントがゼロになるまで待つ
 latch.await();

 System.out.println("All Finish !!!");

 // 結果を取得する
 for (String s : result) {
 System.out.println("answer = " + s);
 }

 } catch (InterruptedException e) {
 System.out.println(e);
 }

 }
}

四つのスレッドが全て終わるのを待ち合わせなくても良いなら、CountDownLatch も要らないですね。

 for (int i = 0 ; i < 4 ; ++i) {
 (new MyThread(i, result)).start();
 }

 for (int i = 0 ; i < 4 ; ++i) {
 // 計算が終わったものから、結果を取り出す
 String s = result.take();
 System.out.println("answer = " + s);
 }

zachouRさんのコメント
わざわざ、ありがとうございます!大変参考になりました! こちらのも参考に、さっそく組み込みました!

a-kuma3さんのコメント
何か、すっきりしない感じだったので、追記しました。

zachouRさんのコメント
ありがとうございました。大変参考になりました。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ