在我的rails控制器方法中运行线程

时间:2013-11-18 22:30:32

标签: ruby-on-rails ruby multithreading actioncontroller

我有一组数据,我想在我的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的每个成员实例返回一堆空数组,但是,如果我将这些线程连接在一起,它会运行,但由于每个线程都阻塞,因此无法进行线程化。< / p>

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

谢谢,

1 个答案:

答案 0 :(得分:12)

首先取决于您的计算是执行处理器繁重的操作还是正在执行大量阻塞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

希望有所帮助。