3

私はこのクラスを持っています:

public class MyThread implements Runnable {

    private static boolean canAccess = true;
    private Thread t;

    public FirstThread(String name) {
    t = new Thread(this);
    t.setName(name);
    }

    public void start() {
        t.start();
    }

    private synchronized void accessed(String name) throws InterruptedException {
    if (canAccess) {
        canAccess = false;
        System.out.println("Accessed " + name);
        try {
        Thread.sleep(5000);
        } catch (Exception e) {
        }
        canAccess = true;
        System.out.println("NOTIFY: " + name);
        notifyAll();
    }
    System.out.println("WAIT: " + name);
    wait();

    }

    @Override
    public void run() {
    while (true) {
        try {
        accessed(Thread.currentThread().getName());
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
    }
    }
}

そして、これは私の出力です:

Accessed 1
WAIT: 3
WAIT: 5
WAIT: 7
WAIT: 9
WAIT: 0
WAIT: 2
WAIT: 4
WAIT: 6
WAIT: 8
NOTIFY: 1
WAIT: 1

そして私のアプリはフリーズします(デッドロック状態)。notifyAll メソッドが機能しないようです。私のエラーはどこですか?

私のメインクラス。

public class Main {

    public static void main(String[] args) {
    MyThread [] threads = new MyThread[10];
    for(int i=0;i<threads.length;i++) {
        threads[i] = new MyThread(""+i);
        threads[i].start();
    }

    }

}
4

2 に答える 2

2

waitスレッドがロックを解放し、別のスレッドが通知するまで休止状態になることを意味します。notifyAllスレッドは、現在の同期ブロックで使用されているロックを待機している他のすべてのスレッドに、ウェイクアップしてロックを再度取得するように指示することを意味します。コード例には、複数のスレッドが同じロックを取得しようとするケースがないため、ここで wait と notifyAll を使用しても意味がありません。スレッドが待機を呼び出すと、スレッドをウェイクアップするものは何もありません。

待機と通知の典型的な使用方法の 1 つ: キューにデータを入れる多くのプロデューサーと、キューからデータを取り出すコンシューマー スレッドがある場合があります。キューには、コンシューマーが呼び出す take メソッドがあり、キューが空の場合は wait を呼び出し、コンシューマーはブロックします。キューには、何かがキューに入ったときに notifyAll を呼び出す put メソッドがあり、待機中のコンシューマー スレッドが起動します。

Java チュートリアルには、wait と notifyAll を使用した生産者と消費者の例があります。

于 2012-07-08T15:35:48.660 に答える
1

すべてのスレッドはそれ自身のインスタンスを待機します。そのため、すべてのスレッドが1か所でスタックします。

private static Object LOCK = new Object();があり、LOCK.wait();を呼び出す場合。およびLOCK.notify(); これは別の話かもしれません。

また、accessed()メソッドの同期修飾子についても疑問があります。説明されている状況では使用できません。同期ブロックの「canAccess」変数を変更したほうがよいでしょう。

于 2012-07-08T15:06:26.703 に答える