【问题标题】:Running threads inside my rails controller method在我的 rails 控制器方法中运行线程
【发布时间】:2013-11-18 22:30:31
【问题描述】:

我有一组数据,我想在我的 rails 应用程序中进行一些计算,每个计算都是相互独立的,所以我想对它们进行线程化,这样我的响应速度会快得多。

这是我的 ATM:

def show

  @stats = Stats.new

  Thread.new {
    @stats.top_brands = #RESULT OF FIRST CALCULATION     
  }

  Thread.new {
    @stats.top_retailers = #RESULT OF SECOND CALCULATION
  }

  Thread.new {
    @stats.top_styles = #RESULT OF THIRD CALCULATION
  }

  Thread.new {
     @stats.top_colors = #RESULT OF FOURTH CALCULATION
  }

  render json: @stats
end

现在这会为@stats 的每个成员实例返回一堆空数组,但是,如果我将线程连接在一起,它会运行,但由于每个线程都阻塞,因此无法实现线程化的目的。

由于我对线程非常陌生,我想知道我在这里做错了什么,或者是否有可能完成我正在尝试做的事情,即并行运行 4 次计算并将结果返回到客户。

谢谢,

【问题讨论】:

    标签: ruby-on-rails ruby multithreading actioncontroller


    【解决方案1】:

    这首先取决于您的计算是在执行处理器繁重的操作还是执行大量阻塞 IO,例如从数据库、文件系统或网络读取。如果他们做前者,那不会有太大的好处,因为每个线程都占用 CPU 时间,并且没有其他线程可以调度 - 更糟糕的是,即使您使用的是具有 Global Interpreter Lock 的 Ruby MRI。但是,如果线程正在执行阻塞 IO,它们至少可以等待,让另一个线程运行,等待,让另一个线程运行等等,直到它们全部返回。

    最后,您必须将所有线程连接在一起,因为您需要它们的返回值。在所有 Thread.new 调用下执行此操作。将每个 Thread.new 的返回值保存到一个数组中:

    threads = []
    threads << Thread.new ...
    

    然后在渲染之前将它们连接在一起:

    threads.each &:join
    

    如果您想真正确定这对您有帮助,只需对整个操作进行基准测试:

    def show
      start_time = Time.now.to_f
      @stats = Stats.new
    
      Thread.new {
        @stats.top_brands = #RESULT OF FIRST CALCULATION     
      }
      Thread.new {
         @stats.top_colors = #RESULT OF FOURTH CALCULATION
      }
    
      @elapsed_time = Time.now.to_f - start_time
      # do something with @elapsed_time, like putsing it or rendering it in your response
    
      render json: @stats
    end
    

    希望对您有所帮助。

    【讨论】:

    • 是的,但是为了让它真正起作用,我必须使用 JRuby 之类的东西,对吧?
    • 如果您的线程中的计算正在执行阻塞 IO,您仍然会看到加速。这使它们进入睡眠状态,并且可以安排其他线程开始它们的工作。您可以看到它是如何工作的:gist.github.com/DiegoSalazar/7547566#file-sleepy_threads-rb 可以确定的最快方法是在有线程和无线程的情况下对您的操作进行基准测试。
    • 但是,在 JRuby、Rubinius、Ruby EE 中会更好,因为它们将能够使用您机器上的所有内核来运行本机线程。
    • 假设我在每个线程中连接到一个 mongodb 实例并处理一些数据。那,如果我理解正确,非阻塞 I/O 是否正确?因此,即使在 MRI 中我也应该看到加速?
    • 我不确定你用来连接 mongodb 的客户端库是执行阻塞还是非阻塞 IO。但它是一种网络操作,通常是阻塞的。就像我说的,你应该对你的方法进行有无线程的基准测试以获得更好的想法。
    猜你喜欢
    • 2013-09-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 2014-04-12
    • 1970-01-01
    • 2012-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多