wait()を実行した後、他のスレッドから通知を受け取らない場合、スレッドはどのくらい待機しますか?

Aug 16 2020

以下の例では、メインスレッドは子スレッドから通知を受け取っていないため、永久に待機する必要があります。しかし、メインスレッドは実行されており、以下の例の出力は次のとおりです。

c
l
total: 19900

メインスレッドが実行されるのはなぜですか?

public class ThreadX extends Thread {
    static int total = 0;

    public void run() {
        synchronized (this) {
            for (int i = 0; i < 200; i++) {
                total = total + i;
            }
            System.out.println("c");

        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadX t = new ThreadX();

        t.start();
        synchronized (t) {
            t.wait();
            System.out.println("l");
        }

        System.out.println("total: " + total);

    }
}

回答

10 akuzminykh Aug 16 2020 at 09:58

質問への回答-本文

チェックアウトThread#join(long):

[...]スレッドが終了すると、this.notifyAllメソッドが呼び出されます。[...]

Thread#join()その関数を0、で呼び出すことに注意してください。これは永遠を意味します。

[...]タイムアウト0は、永久に待機することを意味します。

したがって、あなたの場合、ここtではnotifyAll終了時に呼び出すだけで、待機しているメインスレッドに通知しtます。


この直感的でない動作が、ドキュメントに次のように書かれている理由です。

アプリケーションが使用しないことをお勧めしますwaitnotifyまたはnotifyAllThreadのインスタンス。

質問への回答-タイトル

チェックアウトObject#wait(またはJLS(17.2.1。待機)):

スレッドは、通知、中断、またはタイムアウトすることなく、いわゆるスプリアスウェイクアップでウェイクアップできます。これが実際に発生することはめったにありませんが、アプリケーションは、スレッドをウェイクアップさせるはずの条件をテストし、条件が満たされない場合は待機し続けることによって、これを防ぐ必要があります。

したがって、Javaのスレッドはいつでもウェイクアップできます。偽のウェイクアップはほとんど発生しませんが、発生する可能性があります。