1

わかりました、それで、誰かがここでの私の知識のギャップを説明してもらえますか?

以下の例では、最初はインスタンス メソッドを同期しようとしていましたが、その後、新しいインスタンスを生成したため、ロックが発生しないことに気付きました。

そこで、スレッドが正常に実行されることを期待して、クラスの静的メソッドをロックすることにしましたが、それでもうまくいきません。私のやり方の誤りを説明できる人はいますか? (理解を深めるだけで、これを行うためのより良い方法がおそらくあるのでご了承ください。私はJavaを使用するPHP開発者です。大好きです-しかし、私はたった2日です;-))

したがって、この時点では数字はランダムな順序で出力されます。

クラス1

package learningjava;


public class LearningJava {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

      ThreadCaller ob1 = new ThreadCaller("This is a test string 1");
      ThreadCaller ob2 = new ThreadCaller("This is a test string 2");
      ThreadCaller ob3 = new ThreadCaller("This is a test string 3");
      ThreadCaller ob4 = new ThreadCaller("This is a test string 4");
      ThreadCaller ob5 = new ThreadCaller("This is a test string 5");

      try {

           ob1.t.join();
           ob2.t.join();
           ob3.t.join();
           ob4.t.join();
           ob5.t.join();

      } catch (InterruptedException e) {

          System.out.println(e);

      }

    }    

}

クラス2

package learningjava;

public class ThreadCaller implements Runnable {

    private String message;
    public Thread t;

    public ThreadCaller(String text) {
        message = text;
        t = new Thread(this);
        t.start();
    }

    public static synchronized void echo(String message) {
        System.out.println(message);
    }


    public void run() {
            ThreadCaller.echo(this.message);
    }

}
4

3 に答える 3

1

私のやり方の誤りを説明できる人はいますか?

基本的に、あなたは単に保証されていない注文を期待しています. 多くのスレッドを連続して呼び出しstart()ています...どのスレッドが実際に最初に実行を開始するかについての保証はありません。静的同期メソッドを持っているという事実は、一度に 1 つのスレッドのみがそのメソッドを実行することを意味します。順序については何も保証されません。

100m 先に 1 車線のゲートがあるランニング トラックがあるとします。あなたがレースを開始します。どのランナーが最初にゲートに到着しますか?

幸いなことに、これは通常は問題になりません。何かを行うために複数のスレッドを開始する価値がある場合は、通常、それらが実行される順序は気にしません。もしそうなら、それはあなたのデザインを再検討する時です.

于 2012-07-07T07:54:59.940 に答える
1

スレッドのスケジューリングは予測できません。

あなたがやろうとしていることは、ある意味でその目的を打ち負かしていますよね?

順序が必要な場合は、実行を順次にするか、ExecutorServiceで呼び出します。

于 2012-07-07T07:56:21.947 に答える
0

スレッドを結合する前にすべてのスレッドを開始しているため、この方法では順序付けを実行できません。

ExecurorService を使用して 1 つのスレッドのプールを作成し、ループ内でスレッドを 1 つずつプールして実行するかの順序を維持できます。

コードの他の方法では、 でスレッドを開始せず、Runnableで開始し、LearningJave1 つずつ開始した直後に参加します。

Thread t1=new Thread(ob1);
   t1.start();
   t1.join();

   Thread t2=new Thread(ob2);
   t2.start();
   t2.join();
 ----
 -----
于 2012-07-07T08:13:29.610 に答える