ruby-on-rails - Rails 线程 - 多任务

标签 ruby-on-rails thread-safety

我正在尝试运行多个任务,每个任务都访问数据库,并且我正在尝试将这些任务运行到单独的执行线路中。

我玩了玩,试过设置为 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 }

谢谢

最佳答案

我最近实现了一个使用线程的 Rails 应用程序并有一些发现:

首先,如果您要在线程外写入任何数组或散列(即复杂类型),请将它们包装在互斥体中。在我看来,散列和数组引用可能不是线程安全的。哈希/数组元素索引似乎不太可能不是线程安全的,但我所知道的是,在写入之前将外部数据结构放入互斥量后,问题就消失了。

其次,当线程终止时关闭您的 ActiveRecord 连接,否则您最终可能会创建大量过时的连接。这是一个 post about how to do this .我不知道它是否仍然适用于 Rails 版本 > 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 是唯一可以利用 native CPU 线程的实现。如果您使用线程以便在等待网络连接或其他一些非 CPU 任务时可以做其他事情,那么这不是问题。

关于ruby-on-rails - Rails 线程 - 多任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1673097/

相关文章:

ruby-on-rails - 使用 Kaminari 过滤分页

ruby-on-rails - 如何在 Rails/ActiveRecord 中同时使用多个聚合函数?

ruby-on-rails - 模板内的 yield 和 provide()

ruby-on-rails - ruby Tmail 错误 : undefined symbol: rb_get_kcode

c# - 使用 C# 的线程池问题

Java 线程同时递增和递减 int

ruby-on-rails - 验证多列的唯一性

c# - 如何使用 ImmutableList<> 而不是 List<> 来获得线程安全?

.net - 并行和线程安全串行模式

java - 将类对象作为同步变量