マルチスレッドの Web クローラーを作成しようとしています。
私のメインのエントリ クラスには、次のコードがあります。
ExecutorService exec = Executors.newFixedThreadPool(numberOfCrawlers);
while(true){
URL url = frontier.get();
if(url == null)
return;
exec.execute(new URLCrawler(this, url));
}
URLCrawler は、指定された URL をフェッチし、HTML を解析してそこからリンクを抽出し、見えないリンクを最前線に戻すようにスケジュールします。
フロンティアは、クロールされていない URL のキューです。問題は get() メソッドの書き方です。キューが空の場合は、URLCrawlers が終了するまで待ってから再試行する必要があります。キューが空で、現在アクティブな URLCrawler がない場合にのみ null を返す必要があります。
私の最初のアイデアは、現在動作中の URLCrawler の数をカウントするために AtomicInteger を使用し、notifyAll()/wait() 呼び出しに補助オブジェクトを使用することでした。各クローラーは、開始時に現在動作中の URLCrawlers の数を増やし、終了時にそれを減らし、完了したことをオブジェクトに通知します。
しかし、notify()/notifyAll() と wait() は、スレッド通信を行うためのやや非推奨のメソッドであると読みました。
この作業パターンでは何を使用すればよいですか? M の生産者と N の消費者の場合と同様に、問題は生産者の疲弊にどう対処するかです。