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

2024-03-27

我有 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() 阻塞。然而,它不是一个永恒的块。有时,其中一个爬虫可以继续前进,但它们会卡住一分钟多。目前,我看不到其中任何一个正在发生。

你知道这是怎么发生的吗?


None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 LinkedBlockingQueue.take() 即使有元素也会阻塞? 的相关文章

随机推荐