我在Postgres数据库的Content表中有250万条记录,我需要遍历这250万条记录中的每一条并执行一些操作(其中许多都是自己很慢)并在最后更新记录根据我在路上收集的内容 - 一切正常 - 问题,这需要血腥的运行。
我遇到了几篇关于多线程这样的工作的文章(我之前在C中做过这个,但从来没有Ruby)和在Ruby中使用线程的优点和缺点,尽管有这些缺点,我可以得到2000个线程off比没有线程运行快得多,但我一次只能关闭2000,限制我实际上能够更新所有250万条记录。这是我的代码:
Content.all.each do |content|
threads << Thread.new do
grab_and_store(content)
end
index += 1
index % 100 == 0 ? (puts index) : nil
end
threads.map(&:join)
我还读到了线程池,一旦完成了原来的工作,就使用相同的线程来完成其他工作,但我似乎无法让它工作。这是我的代码:
POOL_SIZE = 1000
jobs = Queue.new
Content.all.each{ |x| jobs.push x }
workers = (POOL_SIZE).times.map do
Thread.new do
begin
while x = jobs.pop(true)
grab_and_store(x)
end
rescue ThreadError
end
end
end
workers.map(&:join)
当我运行这个时,我得到一个错误,我无法在零级别上执行.join,这意味着工人在此结束时是零。但是,当我接受基于此的代码(如下所示,并source)并运行它完美无缺。我似乎无法弄清楚我的打破方式/如何最好地实现线程池以阻止我的代码在2000线程之后耗尽资源。
谢谢!
P.S。下面是我使用的教程中的代码:
require 'thread'
work_q = Queue.new
(0..50).to_a.each{|x| work_q.push x }
workers = (0...4).map do
Thread.new do
begin
while x = work_q.pop(true)
50.times{print [128000+x].pack "U*"}
end
rescue ThreadError
end
end
end; "ok"
workers.map(&:join); "ok"
更新
根据安东尼的回答,我发现自己使用了以下大块代码,使用他推荐的ruby-thread gem,它很快就完成了给定的内容(它的样本大小为1000),但是当我检查控制台时,它似乎只保存了大约20个。这是代码:
pool = Thread.pool(5)
@ids = []
arr = Content.where(needs_update: true)[0...1000]
puts "Starting With Sample 1000"
arr.each do |content|
pool.process do
grab_and_store(content)
end
index += 1
index % 100 == 0 ? (puts index) : nil
end
pool.shutdown