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

「そして、さらにいくつかの詳細があります。それを実践的なアドバイスと呼びましょう。」

「何かを待機し、条件が満たされるまでスリープするメソッドがあるとします。」

コレクションが空の場合は待機します
public synchronized Runnable getJob()
{
 if (jobs.size() == 0)
  this.wait();

 return jobs.remove(0);
}

「Java ドキュメントでは、ループ内で wait メソッドを呼び出すことを強く推奨しています。」

コレクションが空の場合は待機します
public synchronized Runnable getJob()
{
 while (jobs.size() == 0)
  this.wait();

 return jobs.remove(0);
}

「なぜですか? 問題は、スレッドが目覚めても、それは条件が満たされたことを意味しないということです。おそらく、そのような眠っているスレッドが 20 個あったでしょう。それらはすべて目覚めましたが、タスクを実行できるのは 1 つだけです。」

「大まかに言えば、『誤報』が存在する可能性があります。優れた開発者はこれを考慮する必要があります。」

「なるほど、notifyを使ったほうが楽じゃないですか?」

「リストに複数のタスクがあった場合はどうなるでしょうか? 通常、最適化のために Notify を使用することをお勧めします。それ以外の場合はすべて、notifyAll メソッドを使用することをお勧めします。」

"OK。"

「しかし、それだけではありません。まず、誰かがあなたのクラスを継承し、独自のメソッドを追加し、さらに wait/notifyAll を使用する状況が存在する可能性があります。言い換えれば、独立した wait/notifyAll ペアが同じオブジェクトを待機する状況が存在する可能性があります。お互いのことを知りません。それでどうすればいいですか?」

「常にループ内で wait を呼び出し、ループの終了条件が true であることを確認してください。」

「そうです。そして、これを回避できないことを明確にするために、多くの開発者は、スレッドが自動的に起動することがあると指摘しています。スレッドは、誤って起動しないことが保証されています。これは、コード最適化の副作用であるようです。 Java マシンを実行しています。」

「おお、わかりました。ループがないと、wait メソッドは役に立ちません。」