为什么LinkedBlockingQueue.take()即使有元素也会阻止?

时间:2012-07-14 16:35:58

标签: java multithreading

我有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;
}

为了调试目的,我只添加了synchronizedqueue.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()中被阻塞。然而,这不是一个永恒的障碍。有时爬行器可以继续,但它们会被卡住超过一分钟。目前,我看不到他们中的任何一个。

你知道这会怎么样吗?

0 个答案:

没有答案