Javaにおける待機とスリープの違い

1概要

この短い記事では、コアJavaの標準の sleep() メソッドと wait() メソッドを見て、それらの違いと類似点を理解します。

2 Wait Sleep の一般的な違い

簡単に言うと、 wait() はスレッドの同期に使用されるインスタンスメソッドです。

__java.lang.Objectで定義されているように、どのオブジェクトに対しても呼び出すことができます。別のスレッドがジャンプしてロックを取得できるように、オブジェクトのロックを解除します。

一方、 Thread.sleep() は任意のコンテキストから呼び出すことができる静的メソッドです。 ** Thread.sleep() は現在のスレッドを一時停止し、ロックを解除しません。

これが、実行中のこれら2つのコアAPIの非常に単純化された初期外観です。

private static Object LOCK = new Object();

private static void sleepWaitExamples()
  throws InterruptedException {

    Thread.sleep(1000);
    System.out.println(
      "Thread '" + Thread.currentThread().getName() +
      "' is woken after sleeping for 1 second");

    synchronized (LOCK) {
        LOCK.wait(1000);
        System.out.println("Object '" + LOCK + "' is woken after" +
          " waiting for 1 second");
    }
}

この例を実行すると、以下の出力が生成されます。

1秒間スリープした後に メインスレッドが起動します 1秒間待機した後に オブジェクト ' [email protected ]が起動します

3ウェイトとスリープを起こす

sleep() メソッドを使用すると、中断されない限り、スレッドは指定された時間間隔の後に開始されます。

wait() では、起動プロセスはもう少し複雑です。待機しているモニターで notify() メソッドまたは notifyAll() メソッドを呼び出すことによって、スレッドを起動できます。

待機状態にあるすべてのスレッドをウェイクアップする場合は、 notify() の代わりに notifyAll() を使用してください。 wait() メソッド自体と同様に、 notify() notifyAll() は同期コンテキストから呼び出す必要があります。

たとえば、以下のようにして 待つ ことができます。

synchronized (b) {
    while (b.sum == 0) {
        System.out.println("Waiting for ThreadB to complete...");
        b.wait();
    }

    System.out.println("ThreadB has completed. " +
      "Sum from that thread is: " + b.sum);
}

それから、モニタ上で__notify()を呼び出して、別のスレッドが待機中のスレッドを** ウェイクアップする方法を次に示します。

int sum;

@Override
public void run() {
    synchronized (this) {
        int i = 0;
        while (i < 100000) {
            sum += i;
            i++;
        }
        notify();
    }
}

この例を実行すると、以下の出力が生成されます。

スレッドBが完了するのを待っています…​ スレッドBが完了しました。 合計 そのスレッドから:704982704

4結論

これは、Javaの wait sleep のセマンティクスの概要です。

一般に、1つのスレッドの実行時間を制御するには sleep() を、マルチスレッド同期には wait() を使用する必要があります。基本を十分に理解した上で、当然のことながら探索することがもっとたくさんあります。

いつものように、この記事https://github.com/eugenp/tutorials/tree/master/core-java-concurrency[GitHubについて]で提供されている例をチェックすることができます。