如果不是最大值,同时仍然保持高效?
我正在创建14个线程,每个线程打开一个URL列表(大约500个),为每个线程创建一个新线程,然后下载它,并将其添加到MySQL数据库。 MySQL池大小设置为50。
这是RoR中的rake任务。
使用Kernal#fork
或其他方法会更好吗?
答案 0 :(得分:12)
require 'open-uri'
a = 'http://www.example.com ' * 30
arr = a.split(' ')
arr.each_slice(3) do |group|
group.map do |site|
Thread.new do
open(site)
p 'finished'
end
end.each(&:join)
end
答案 1 :(得分:3)
使用Ruby 1.8,它实际上仅限于你拥有多少内存。您可以为每个进程创建数万个线程。 Ruby解释器处理线程的管理,只创建一个或两个本机线程。 CPU不在线程之间切换,这不是真正的多任务处理。
Ruby 1.9使用本机线程。限制似乎是操作系统允许的限制。仅仅是为了测试,我可以在操作系统不再允许的情况下使用Ruby 1.9在我的mac上创建超过2000个线程。
请注意,拥有数千个进程的线程并不是一个好主意。在此之前,线程调度成为一种负担。
答案 2 :(得分:3)
好吧,既然你的线程将是IO绑定的,那么好消息是Ruby 1.8和1.9线程都适用于此。 Ruby 1.8使用“用户空间线程”,这意味着在Ruby中创建新线程时不会创建真正的新OS线程。这对CPU多任务处理很不利,因为一次只有一个Ruby线程实际运行,但对多任务处理有利。 Ruby 1.9使用真正的线程,对两者都有好处。
您可以创建的线程数取决于您的系统。当然有实际的限制,但你可能不希望靠近它们。首先,除非您所关注的服务器非常慢并且连接速度非常快,否则只需几个线程即可使您的Internet连接饱和。此外,如果你从一台服务器上抓取了很多页面,那么从500个线程中同时抛出500个请求也不会有任何好处。
我开始很小:一次运行10或20个线程。根据服务器负载,带宽等增加或减少这一点。还存在与MySQL数据库并发连接的问题。根据表的设置方式和表的大小,尝试同时插入太多数据并不会很好。