具有未知任务数的多线程

时间:2016-01-21 12:35:13

标签: multithreading grails groovy

我正在为拥有越来越多实体的网站实施抓取工具。没有可用信息存在多少实体且没有所有实体的列表。可以使用以下URL访问每个实体:http://www.somewebsite.com/entity_{i}其中{i}是实体的编号,从1开始并以1递增。

要抓取每个实体,我正在运行一个循环,检查HTTP请求是否返回200404。如果我得到404 NOT FOUND,则循环停止,我确定我拥有所有实体。

串行方式如下:

def atTheEnd = false
def i = 0
while(!atTheEnd){
    atTheEnd = !crawleWebsite("http://www.somewebsite.com/entity_" + i)
    i++
}

crawleWebsite()如果成功则返回true,如果出现404 NOT FOUND错误则返回false。

问题是抓取这些实体可能需要很长时间,这就是为什么我想在多个线程中执行它但我不知道实体的总量,因此每个任务都不是独立的其他任务。

解决这个问题的最佳方法是什么?

我的方法是:使用带有REST HEAD请求的二进制搜索来获取实体总数(介于500和1000之间)并将其拆分为某些线程。

有没有更好的方法呢?

TL;博士

基本上我想告诉线程池以编程方式创建新任务,直到满足条件(发生第一个404时)并等待每个任务完成。

注意:我使用Grails 3实现此代码。

1 个答案:

答案 0 :(得分:1)

正如你所说,实体的总数是未知的,可以分为数千个。在这种情况下,我只是寻找一个固定的线程池并推测性地查询URL,即使你可能已经到了最后。考虑这个例子。

size=

线程池设置为50,一旦抓取所有50个URL,我们检查是否到达终点。如果不是,我们继续。

显然,在最糟糕的情况下,您可以抓取50 @Grab(group = 'org.codehaus.gpars', module = 'gpars', version = '1.2.1') import groovyx.gpars.GParsPool //crawling simulation - ignore :-) def crawleWebsite(url) { println "$url:${Thread.currentThread().name}" Thread.sleep (1) Math.random() * 1000 < 950 } final Integer step = 50 Boolean atTheEnd = false Integer i = 0 while (true) { GParsPool.withPool(step) { (i..(i + step)).eachParallel{atTheEnd = atTheEnd || !crawleWebsite("http://www.somewebsite.com/entity_" + it)} } if (atTheEnd) { break } i += step } 秒。但我相信你可以逃脱它: - )