5

異なるクラスの 2 つの異なるインスタンスを実行する 2 つの別個のスレッドを用意し、同時に run コマンドを実行させたいと考えています。

私が抱えている問題を実証するために、練習クラスを作成しました。一方のレーサーは順方向に数え、もう一方のレーサーは逆方向に数えます。

public class testCount {

    public static void main(String args[]) {
        testCount countCompetition = new testCount();
        countCompetition.run();
    }

    public void run() {
        (new Thread(new racer1())).start();
        (new Thread(new racer2())).start();
    }

    public class racer1 implements Runnable {
        public void run() {
            for(int x = 0; x < 100; x++) {
                System.out.println(x);
            }
        }
    }
    public class racer2 implements Runnable {
        public void run() {
            for(int y = 100; y > 0; y--) {
                System.out.println(y);
            }
        }
    }
}

私の結果

1
2
... All the way to 100
100
100
99
... All the way back down
1

私が欲しいもの

1
100
2
99
3
98

彼らはそのように交代する必要はありませんが、次々とではなく、同時に作業する必要があります。ヒント、アドバイス、またはコード スニペットをいただければ幸いです。

4

3 に答える 3

7

これまでのすべての答えには要点が欠けていると思います。

既存のロジックでは、2 つのスレッドを同時に実行できますが、数値が 100 までしか上がらず、実行は通常、一度に複数の命令に対して特定のスレッドにとどまるため、これは明らかではありません。現在実行中のスレッドを常に切り替えると、大量のオーバーヘッドが発生します。あなたの場合、JVMは、2番目のスレッドへの「コンテキスト切り替え」の前に、100個の数字を出力するのに十分な時間、最初のスレッドを実行することを決定しています。JVM はスレッドを異なる方法で実行することを選択する場合があるため、表示される結果が毎回同じであるとは限りません。

数を 1000 まで増やすと、(おそらく) 2 つのスレッドが多少インターリーブすることがわかります。JVM は、すべての命令間でコンテキストを切り替えるのではなく、切り替える前にしばらくの間 1 つのスレッドを実行する方が効率的であるため、1 つのスレッドが連続して多数の数値を出力する大規模な実行が引き続き発生します。

不必要な遅延を追加しているため、 Thread.sleep(1) を追加することは良い解決策ではありません。確かに、100 個の数字ではこれは目立たないかもしれませんが、10000 個の数字では 10 秒の遅延があります。

すでに行っているよりも高度にインターリーブする必要がある理由はありますか? ある場合、2 つのスレッドを同時に実行する単純なモデルでは不十分です。そうでない場合は、JVMにスレッドを実行するための最良の順序を決定させます(これは、与えられた単純な例では、ほとんどの場合インターリーブしないことを意味します)。

于 2013-04-19T08:51:24.883 に答える
-1

基本的な待機および通知システムを作成する必要があります。1 つのタスクは、自分がその仕事を釣り上げたことを他のタスクに通知する必要があります。基本的な考え方は、以下のコードから導き出すことができます。2 つのタスクを作成します。1 つは順方向にカウントするタスク、もう 1 つは逆方向にカウントするタスクです。

Runnable task = new Runnable() {
  public void run() {
    System.out.println("woohooTwo");
    synchronized (t) {
      while (true) {
        System.out.println("---" + Thread.currentThread().getName() + "--" + t.i.getAndIncrement());
        t.notifyAll();

        try {
          Thread.sleep(1000);
          t.wait();
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }

    }
  }
};
于 2013-04-19T08:18:23.020 に答える