4

私はまだJavaの初心者であり、学習スレッドを試してみています。私の質問は、5回ループしないということです。1回実行して終了します。両方のスレッドが同じオブジェクトモニターでロックされるように、a.classを使用してクラスオブジェクトをロックしています。

class a implements Runnable {
  Thread thr;
  int count;
  String time;

  a(String s) {
    thr = new Thread(this, s);
    thr.start();
  }

  public void run() {
    count++;

    if (Thread.currentThread().getName().compareTo("one") == 0) {
      synchronized (a.class) {

        try {
          for (int i = 0; i < 5; i++) {
            System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);

            time = "Tick";
            System.out.println(time);
            notify();

            while (time == "Tock") {
              wait();
            }
          }
        } catch (Exception e) {
        }

      }
    } else if (Thread.currentThread().getName().compareTo("two") == 0) {
      synchronized (a.class) {
        try {
          for (int j = 0; j < 5; j++) {
            System.out.println("Now running thread " + Thread.currentThread().getName() + " with count " + count);

            time = "Tock";
            System.out.println(time);
              notify();

            while (time == "Tick") {
              wait();
            }
          }
        } catch (Exception e) {
        }
      }
    }
  }
}

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

    a obj1 = new a("one");
    a obj2 = new a("two");
  }
}
4

3 に答える 3

3

元のコードを使用すると、次のようになります。

class a implements Runnable {
    Thread thr;
    int count;
    static String time = "Tock";

    a(String s) {
        thr = new Thread(this, s);
        thr.start();
    }

    public void run() {
        count++;

        if (Thread.currentThread().getName().compareTo("one") == 0) {
            synchronized (a.class) {

                try {
                    for (int i = 0; i < 5; i++) {
                        while (time.equals("Tock")) {
                            a.class.wait();
                        }

                        System.out.println("Now running thread "
                                + Thread.currentThread().getName()
                                + " with count " + count);

                        time = "Tock";
                        System.out.println(time);
                        a.class.notify();                       
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        } else if (Thread.currentThread().getName().compareTo("two") == 0) {
            synchronized (a.class) {
                try {
                    for (int j = 0; j < 5; j++) {
                        while (time.equals("Tick")) {
                            a.class.wait();
                        }

                        System.out.println("Now running thread "
                                + Thread.currentThread().getName()
                                + " with count " + count);

                        time = "Tick";
                        System.out.println(time);
                        a.class.notify();                       
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

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

        a obj1 = new a("one");
        a obj2 = new a("two");
    }
}

問題は、オブジェクトでロックが保持されているときに暗黙的なオブジェクトでwaitandを呼び出していたため、 onを呼び出す必要があることでした。それだけでした。notifythisa.classwait/notifya.class

私はまた、あなたがそれらを交互に印刷することを望んでいたと思うので、小さな再構築をTick行いましたよね?Tock

于 2012-09-17T19:32:07.300 に答える
2

文字列(および一般的なオブジェクト)を比較するときは、 (一般的にプリミティブ用に予約されている)ではequalsなく使用する必要があります。文字列上では、多くの場合、戻りたい(そしてそうすべきだと思う)ときに結果が生じるため、ループは予期せずに終了します。==while(time.equals("Tock"))==falsetrue

于 2012-09-11T23:24:53.467 に答える
2

ループが 1 回だけである理由に対する答えはnotify()、ロックされていないオブジェクトを呼び出すためIllegalMonitorStateException、空の catch ステートメントによってスローされ、キャッチされるためです。

これは 1 つの方法です。それが最高だと言っているのではありません。私はそれをあなたのコードに近づけようとしました:

public class TickTock {
    static final int N = 4;

    Object lock = new Object();
    int token;

    class Worker extends Thread {
        int id;

        Worker(int id) {
            this.id = id;
        }

        @Override
        public void run() {
            try {
                synchronized (lock) {
                    for (int i = 0; i < 5; i++) {
                        while (id != token%N) lock.wait();

                        System.out.println(id + " " + i);

                        token++;
                        lock.notifyAll();
                    }
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    void start() {
        for (int i = 0; i < N; i++) {
            new Worker(i).start();
        }
    }

    public static void main(String[] args) {
        new TickTock().start();
    }
}
于 2012-09-11T23:57:03.670 に答える