我有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文档contains()
继承自AbstractCollection
所以我猜这至少与多线程无关,因此也不能成为阻塞的原因。
重点是,从我的调试中我也可以看到其他线程似乎也在list.take()中被阻塞。然而,这不是一个永恒的障碍。有时爬行器可以继续,但它们会被卡住超过一分钟。目前,我看不到他们中的任何一个。
你知道这会怎么样吗?