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つのスレッド全部にフラグを立てるような仕組みをいれてそれを監視するという方法がいいのでしょうか?

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2013/08/20 11:31:25
  • 終了:2013/08/27 11:35:04

回答(2件)

id:Sampo No.1

Sampo回答回数556ベストアンサー獲得回数1042013/08/20 12:20:25

ポイント50pt

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つともスレッドへの参照を取っておいて、すべてについて終了を待ってあげる必要があります。

id:zachouR

わざわざ、ありがとうございます!大変参考になりました!

さっそく組み込みました!

2013/08/20 13:15:56
id:a-kuma3 No.2

a-kuma3回答回数4560ベストアンサー獲得回数19042013/08/20 12:48:44

ポイント50pt

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);
    }
他1件のコメントを見る
id:a-kuma3

何か、すっきりしない感じだったので、追記しました。

2013/08/20 13:22:01
id:zachouR

ありがとうございました。大変参考になりました。

2013/08/22 11:16:34

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません