を共有する10個のWebクローラーがありますLinkedBlockingQueue
。
list.take()
Eclipseのデバッグビューから、複数のURL(約1000)をフェッチすると、呼び出しに非常に時間がかかることがわかりました。
仕組みは次のとおりです。
private (synchronized) URL getNextPage() throws CrawlerException {
URL url;
try {
System.out.println(queue.size());
url = queue.take();
} catch (InterruptedException e) {
throw new CrawlerException();
}
return url;
}
追加synchronized
しqueue.size()
たのは、デバッグの目的で、take()
呼び出されたときにリストが実際にいっぱいになっているかどうかを確認するためだけです。はい、そうです(この実行では1350要素)。
queue.put()
一方、URLが本当に新しい場合にのみ呼び出されます。
private void appendLinksToQueue(List<URL> links) throws CrawlerException {
for (URL url : links) {
try {
if (!visited.contains(url) && !queue.contains(url)) {
queue.put(url);
}
} catch (InterruptedException e) {
throw new CrawlerException();
}
}
}
ただし、他のすべてのクローラーもあまりにも多くの新しいURLを生成するようには見えないため、キューが実際にブロックされることはありません。これは、キューにあるURLの数です(5秒間隔で):
Currently we have sites: 1354
Currently we have sites: 1354
Currently we have sites: 1354
Currently we have sites: 1354
Currently we have sites: 1355
Currently we have sites: 1355
Currently we have sites: 1355
Java doccontains()
はから継承されAbstractCollection
ているため、これは少なくともマルチスレッドとは関係がなく、ブロックする理由にもなり得ないと思います。
ポイントは、私のデバッグから、他のスレッドもlist.take()でブロックされているように見えることもわかります。しかし、それは永遠のブロックではありません。クローラーのオンが続く場合もありますが、1分以上スタックします。現在、私はそれらのどれも起こっているのを見ることができません。
これがどのように起こるか知っていますか?