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について]で提供されている例をチェックすることができます。