「こんにちは、アミーゴ!」

「やあ、リシ!」

「Object クラスのwait メソッドnotify メソッド、およびNoticeAllメソッドを紹介します。」

「今日は彼らと知り合うだけですが、後で戻ってきて、このことにもっと時間を費やすつもりです。」

"わかった。"

「これらのメソッドは、スレッド同期メカニズムの一部として発明されました。」

「Java には、さまざまなスレッドからの共有リソース (オブジェクト) へのアクセスを制御するための組み込みメカニズムがあることを思い出してください。スレッドはオブジェクトがビジーであると宣言でき、他のスレッドはビジーなオブジェクトが解放されるまで待機する必要があります。 」

「覚えています。同期キーワードを使用してそれを行います。」

「そうです。通常、コードは次のようになります。」

public void print()
{
 Object monitor = getMonitor();
 synchronized(monitor)
 {
  System.out.println("text");
 }
}

「その仕組みを覚えていますか?」

「はい。2 つのスレッドが同時に print() メソッドを呼び出すと、そのうちの 1 つが synchronized というラベルの付いたブロックに入り、モニターをロックします。これにより、2 番目のスレッドはモニターが解放されるまで待機することになります。」

「そうです。スレッドが synchronized というラベルの付いたブロックに入ると、モニター オブジェクトはビジーとしてマークされ、他のスレッドはモニター オブジェクトが解放されるまで待機することになります。同じモニター オブジェクトをプログラムのさまざまな部分で使用できます。 」

「ところで、なぜモニターという名前を選んだのですか?」

「モニターとは、通常、ビジーまたはフリーのステータスを保存するオブジェクトと呼ばれるものです。」

「そして、ここで待機メソッドと通知メソッドが登場します。」

「実際には、これらの方法は 2 つだけです。他の方法はこれらの方法を応用したものにすぎません。」

「ここで、 wait メソッドとは何か、そしてなぜそれが必要なのかを理解しましょう。 」

「プログラムでは、スレッドが同期コードのブロックに入ってモニターをロックしても、一部のデータが欠落しているため処理を続行できない状況が発生することがあります。たとえば、処理する必要のあるファイルのダウンロードが完了していない、またはそんな感じ。"

「ファイルがダウンロードされるのを待つこともできます。ループを使用してチェックすることもできます。ファイルがまだダウンロードされていない場合は、1 秒ほどスリープして、ダウンロードされるまで再度確認してください。」

"このようなもの:"

while(!file.isDownloaded())
{
 Thread.sleep(1000);
}
processFile(file);

「しかし、私たちの場合、このタイプの待機はコストが高すぎます。スレッドがモニターをロックしたため、他のスレッドも、必要なデータをすでに持っている場合でも待機することを余儀なくされます。」

wait()メソッドは、この問題を解決するために発明されました。このメソッドにより、スレッドはモニターを解放し、スレッドを「一時停止」します。

「モニター オブジェクトの wait メソッドを呼び出すことができるのは、モニターがビジー状態の場合、つまり同期ブロック内のみです。これが発生すると、スレッドは一時的に実行を停止し、モニターは解放されて他のスレッドが使用できるようになります。」

「スレッドが同期ブロックに入り、待機を呼び出し、モニターを解放する場合がよくあります。」

「その後、2 番目のスレッドが入って一時停止され、次に 3 番目のスレッドが続きます。」

「スレッドはどのように再開されるのでしょうか?」

「そのためには、通知するという 2 番目の方法があります。」

「モニターがビジーな場合、つまり同期ブロック内でのみ、モニター オブジェクトのNotice / NoticeAllメソッドを呼び出すことができます。notifyAllメソッドは、このモニター オブジェクトを待機しているすべてのスレッドを起動します。」

notifyメソッドは 1 つのランダムなスレッドを「解凍」しますが、notifyAllメソッドはこのモニターの「凍結」されたすべてのスレッドを解凍します。

「とても興味深いですね。ありがとう、リシ」

「wait() メソッドの適応もあります:」

wait() メソッド 説明
void wait(long timeout)
スレッドは「フリーズ」しますが、引数としてメソッドに渡されるミリ秒数を待った後、自動的に「フリーズ解除」されます。
void wait(long timeout, int nanos)
スレッドは「フリーズ」しますが、引数としてメソッドに渡されるナノ秒数を待った後、自動的に「フリーズ解除」されます。

「これをタイムアウト付き待機とも呼びます。このメソッドは通常の待機と同じように機能しますが、指定された時間が経過してもスレッドが起動していない場合は、スレッド自体が起動します。」