当您不知道其实际计数时,如何从频道读取所有项目



我正在尝试实现一个爬虫,它可以访问某个URL,从中收集新的相对URL并构建报告。我正在尝试使用晶体光纤和通道同时执行此操作,如下所示:

urls = [...] # of String
visited_urls = []
pool_size.times do
spawn do
loop do
url = urls.shift?
break if url.nil?
channel.send(url) if some_condition
end
end
end
# TODO: here the problem!
loop do
url = channel.receive?
break if url.nil? || channel.closed?
visited_urls << url
end
puts visited_urls.inspect

但是在这里我有一个问题 - 无限秒loop(它调用channel.receive?直到频道中的最后一项,然后等待永远不会到达的新消息(。存在问题是因为我不知道频道中实际有多少项目,所以我不能像水晶朗指南的并发部分建议的那样做。

因此,当我们不知道频道将存储多少物品并且我们需要接收时,也许有一些好的做法如何使用该频道?谢谢!

一个常见的解决方案是有一个 kill 值。要么作为主数据流的一部分,如下所示:

results = Channel(String|Symbol).new(POOL_SIZE * 2)
POOL_SIZE.times do
spawn do
while has_work?
results.send "some work result"
end
results.send :done
end
end
done_workers = 0
loop do
message = results.receive
if message == :done
done_workers += 1
break if done_workers == POOL_SIZE
elsif message.is_a? String
puts "Got: #{message}"
end
end

或者通过辅助通道发出事件信号:

results = Channel(String).new(POOL_SIZE * 2)
done = Channel(Nil).new(POOL_SIZE)
POOL_SIZE.times do
spawn do
while has_work?
results.send "some work result"
end
done.send nil
end
end
done_workers = 0
loop do
select
when message = results.receive
puts "Got: #{message}"
when done.receive
done_workers += 1
break if done_workers == POOL_SIZE
end
end

相关内容

  • 没有找到相关文章

最新更新