1. 概要

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

2. 待機スリープの一般的な違い

簡単に言えば、 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秒間スリープした後にウェイクアップされます
オブジェクト’java.lang.Object @ 31befd9f’は、1秒間待機した後にウェイクアップされます

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(); 
    } 
}

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

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

4. 結論

これは、Javaでのwaitおよびsleepのセマンティクスの簡単な入門書です。

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

いつものように、GitHubでこの記事で提供されている例を確認できます。