共有FIFOキュー(マルチコンシューマー/マルチプロデューサー)を持つ並列化されたWebクローラーをプログラムしたいとします。キューにはURLのみが含まれます。キューの終わりを検出するにはどうすればよいですか?
ワーカープロセスは、キューからURLを取得してクロールし、見つかったURLをキューに追加するため、常にコンシューマーとプロデューサーを同時に使用します。このシナリオでは、コンシューマータスクとプロデューサータスクに別々のプロセスを設定する方法はないと思います。
入力データの量は不明ですが無限ではないので、キューの番兵として「ポイズンピル」を使用することは不可能ですよね?
また、キューのサイズは、キューが空であるかどうかを確認するための信頼できる方法ではありません(複数のコンシューマー/プロデューサーのため)。
私を啓発してください:-)
主な問題は、無限ループを防ぐためにURLグラフのサイクルを処理する必要があることです。同じURLをもう一度表示する場合は、おそらくどのキューにも入れないでください。
サイクルの検出と防止が与えられると、キューは最終的にゼロノードに収束し、ゼロキューサイズテストの信頼性が高まります。
センチネルを使用でき、世代の終わりを示すために使用できます。
または、世代ごとに新しいキューを使用できます。したがって、ワーカーは、次世代キューへの書き込み中に、現在の世代キューからの読み取りを開始します。ワーカーは、現在構成されている入力キューが空であることを認識すると、空でないキューから読み取るように再構成し、その後、次のキューに書き込みます。
各世代のキューは、ワーカーがすべて別のキューからの読み取りに移行したときに廃止できます。 (サイクルを検出するためにまだいくつかのデータ構造が必要なモジュロ。)
世代数の概念を使用して、検索が行き過ぎた場合に検索を制限することもできます。時間ベースの終了やURLカウントベースの終了よりも一貫した結果が得られる可能性があります。