スレッド同期waitとnotifyの使用例

1718 ワード

区間[0,1000]の範囲内の偶数の個数を統計する必要がある場合は、次のコードを使用します.
public class Test {

    private static int counter = 0;

    private static class CountRunnable implements Runnable {
        public void run() {
            for (int i = 0; i < 10; ++i) {
                if (i % 2 == 0) {
                    counter += 1;
                }
            }
        }
    }

    public static void main(String []args) throws InterruptedException {
        Runnable r = new CountRunnable();
        Thread t = new Thread(r);
        t.start();
        System.out.println("counter=" + counter);
    }
}

実行後、結果は常に0であることが分かった.これは、スレッドがt起動を開始した後、runメソッドが実行される前に、メインスレッドが実行済みであるためである.この問題を解決するために、t.start()の後にsleepを追加してこの問題を解決することができる.
この問題はsleepによって解決できるが、解決策は柔軟で優雅ではなく、スレッド間の同期メカニズムによって徹底的に解決され、t.start()の後に次のコードを追加することができる.
synchronized (t) {
    t.wait();
}

このコードの役割は、t.start()がnotify()を呼び出す前に、プライマリスレッドがwaitの状態にあることです.
 
t.start()にnotify()メソッドが呼び出されたと推測され、検証のためsynchroizedにsleep()を付けることができ、これによりt.start()実行が完了しnotify()メソッドが呼び出された後、t.wait()がまだ実行されていないため、t.wait()に実行されると、プログラムはここで死んでしまう.notify()呼び出しがないためである.