1

以下のような2つのスレッドを使用してそれをやろうとしています。誰かが私がここでやっている明らかな間違いを指摘できますか?

public class OddEven {

public static boolean available = false;
public static Queue<Integer> queue = new LinkedList<Integer>();

static Thread threadEven = new Thread() {
    @Override
    public void run() {
        printEven();
    }

    public synchronized void printEven() {
        while (!available) {
            try {
                wait();
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }

        System.out.println(queue.remove());

        available = false;
        notifyAll();
    }
};

static Thread threadOdd = new Thread() {
    @Override
    public void run() {
        printOdd();
    }

    public synchronized void printOdd () {
        while (available) {
            try {
                wait();
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
        }

        System.out.println(queue.remove());

        available = true;
        notifyAll();
    }
};

public static void main(String[] args) {
    int n = 20;
    for (int i = 1; i < n; i++) {
        queue.add(i);
    }

    threadOdd.start();
    threadEven.start();

    try {
        Thread.sleep(60000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    try {
        threadOdd.join();
        threadEven.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}

しかし、このプログラムは 1 を出力して終了するだけです。1 を出力した後、available は true になり、printEven はウェイクアップし、出力して available を false に設定する必要があります。ここで何が問題なのかわかりませんか?他の解決策を見ましたが、私の解決策が機能しない理由を知りたいです。

4

1 に答える 1

1

インスタンス メソッドに同期を設定するということは、そのメソッドを呼び出すスレッドがそのインスタンスのロックを取得する必要があることを意味します。public void synchronized printOdd()の構文シュガーです

public void printOdd() {
    synchronized(this) {
        ...
    }
}

ThreadOddthisと threadEven は 2 つの異なるオブジェクトであり、それぞれが独自のロックを使用するため、 はインスタンスごとに異なります。メソッド notifyAll および wait は、ロックとして使用されているオブジェクトで呼び出されます。1 つのスレッドが待機している場合、通知は、通知スレッドと同じロックで待機している他のスレッドにのみ適用されるため、通知されることはありません。

于 2014-12-09T01:43:19.553 に答える