我有 10 个网络爬虫,它们共享一个LinkedBlockingQueue
.
从 Eclipse 中的调试视图中,我发现当我获取多个 URL(大约 1000 个)时,list.take()
通话时间很长。
它是这样工作的:
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
and 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文档contains()
继承自AbstractCollection
所以我想这至少与多线程没有任何关系,因此也不能成为阻塞的原因。
重点是,从我的调试中我还可以看到其他线程似乎也被 list.take() 阻塞。然而,它不是一个永恒的块。有时,其中一个爬虫可以继续前进,但它们会卡住一分钟多。目前,我看不到其中任何一个正在发生。
你知道这是怎么发生的吗?