我正在尝试编写一个多线程的网络爬虫。Java ThreadPool用法
我的主入口类具有下面的代码:
ExecutorService exec = Executors.newFixedThreadPool(numberOfCrawlers);
while(true){
URL url = frontier.get();
if(url == null)
return;
exec.execute(new URLCrawler(this, url));
}
的URLCrawler获取指定的URL,解析HTML链接提取从它,和时间表看不见的链接回到前沿。
边界是未爬行URL的队列。问题是如何编写get()方法。 如果队列为空,它应该等到任何URLCrawlers完成后再重试。 只有当队列为空且当前没有活动的URLCrawler时,它才应返回null。
我的第一个想法是使用AtomicInteger来计算工作URLCrawlers的当前数量和notifyAll()/ wait()调用的辅助对象。每个爬虫在开始时递增当前工作的URLCrawler的数量,并在退出时递减它,并通知对象它已完成。
但我读了notify()/ notifyAll()和wait()是一些不赞成使用的方法来进行线程通信。
我应该在这个工作模式中使用什么?它与M生产者和N个消费者类似,问题是如何处理生产者的繁琐程度。
是的,这是一个稳定状态的解决方案。但是,如果没有任何URLCrawlers排队任何URL,那么如何处理这种情况呢?对于阻塞队列,边界将无限地阻塞。 – 2010-08-04 05:55:17
在这种情况下,您可以在每次UrlCrawler完成工作时调用的边境对象上有一个crawlerDone()方法。这种方法与您建议的计数器方法一起,您可以测试(在您的边界方法中)是否所有抓取工具都已完成。如果这是真的get()可以返回null而不阻塞 – naikus 2010-08-04 06:07:32
边界可以是一个固定容量的阻塞队列。该容量的一个很好的候选者是数字挖掘者号码 – 2010-08-04 18:12:52