我正在尝试运行多个任务,每个任务都访问数据库,我正在尝试将任务运行到单独的执行线中。
我玩过,试过我设置为true的allow_concurrency,或者config.thread_safe!但是我得到了不确定性的错误,例如有时一个类缺失,或者是一个常数......
这是一些代码
grabbers = get_grabber_name_list
threads = []
grabbers.each { |grabber|
threads << Thread.new {
ARGV[0] = grabber
if (@@last_run_timestamp[grabber.to_sym].blank? || (@@last_run_timestamp[grabber.to_sym] >= AbstractGrabber.aff_net_accounts(grabber, "grab_interval").seconds.ago))
Rake::Task["aff_net:import:" + grabber].execute
@@last_run_timestamp.merge!({grabber.to_sym => Time.now})
end
}
}
threads.each {|t| t.join }
谢谢
答案 0 :(得分:3)
我最近实现了一个使用线程的Rails应用程序并做了一些发现:
首先,如果您要在线程外部写入任何数组或哈希值(即复杂类型),请将它们包装在互斥锁中。它看起来像哈希和数组引用可能不是线程安全的。散列/数组元素索引似乎不太可能是线程安全的,但我所知道的是,在写入之前将外部数据结构放入互斥锁之后,问题就消失了。
其次,在线程终止时关闭ActiveRecord连接,否则最终可能会创建大量过时的连接。这是一个post about how to do this。我不知道它是否仍然适用于Rails版本&gt; 2.2但在我明确地开始关闭连接后,我的问题就消失了。作者建议猴子修补ActiveRecord自动执行此操作,但我决定在我的代码中明确释放连接。
这是一个适合我的代码示例:
mutex = Mutex.new
my_array = []
threads = []
1.upto(10) do |i|
threads << Thread.new {
begin
do_some_stuff
mutex.synchronize {
# You'd think that each thread would only touch its own personal
# array element but without a mutex, I run into problems.
my_array[i] = some_computed_value
}
ensure
ActiveRecord::Base.connection_pool.release_connection
end
}
}
threads.each {|t| t.join}
顺便说一下,如果你使用线程来利用多核CPU,你需要使用JRuby。据我所知,JRuby是唯一可以利用本机CPU线程的实现。如果您使用线程以便在等待网络连接或其他非CPU任务时可以执行其他操作,则这不是问题。
答案 1 :(得分:0)
你应该使用后台工作人员这样做。后台工作者库有几个选项,但我最喜欢的是delayed_job(http://github.com/tobi/delayed_job)。
将您发布的代码转换为后台作业应该非常容易。