我有 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
并用于调试目的,以查看列表在被调用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();
}
}
}
但是,所有其他 Crawler 似乎也不会产生太多新 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() 中。然而,它不是一个永恒的障碍。有时,爬虫可以继续运行,但它们会卡住超过一分钟。目前,我看不到他们中的任何一个正在发生。
你知道这怎么会发生吗?