0

关于 stackoverflow 的另一个问题中,我得到一个提示,我可以将线程池​​用于我的爬虫正在创建的生产者-消费者模式。

但是,我只是不知道如何实现它。

SO 上的生产者消费者线程中,他们只使用生产者消费者来管理生产者和消费者(在我的情况下,这将是爬虫本身;这与我的 for 循环没有太大区别),但这似乎不是我文章中评论者的意图(因为他看不到我使用了 for 循环)。工作量仍然通过queue那里共享。

我还考虑过通过这个实现传递一个Website对象(并从中ExecutorService.submit()删除):RunnableCrawler

public class Website implements Runnable {
    private URL url;

    public Website(URL url) {
        this.url = url;
    }

    @Override
    public void run() {
        Crawler crawler = new Crawler();
        crawler.crawl(url);
    }
}

但问题是

  1. 我认为生成的爬虫太多了
  2. Crawler() 需要一个已经访问过的网站队列

如何在爬虫问题中正确实现生产者、消费者模式?我对这一切感到完全困惑。我在网上查了很多关于它的网站,而且似乎都以不同的方式使用它。

4

1 回答 1

0

我想我需要查看更多代码才能理解。
但是,为了拥有生产者-消费者,您可以做的是让您的 Crawler 类成为消费者,
并让代码使用执行程序作为消费者。
Crawler 将从生产者和消费者之间的队列或其他共享数据结构(同步数据结构)中获取 WebSite 对象。
在选择数据结构时,您应该问自己以下一些问题 -
A. 要爬取的站点之间是否有优先级?
如果是这样 - 考虑使用PriorityBlockingQueue

B. 爬取顺序重要但所有优先级都相同吗?
如果是这样 - 考虑使用LinkedBlockingQueue

C. 你能以某种方式对链接进行分类吗?
如果是这样,也许您可​​以拥有多个共享数据结构,并为其提供类别映射。

我相信你可以想出很多关于如何自己构建这个共享数据结构的想法,这些只是我的想法。


总结 -
1. 让 Crawler 扩展 Runnable
2. 让 Crawler 从共享数据结构(即阻塞队列)中提取“作业”(WebSite 类)。
3. 让生产者在使用执行器之前将作业放到共享数据结构中。

于 2012-07-14T20:54:01.197 回答