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

The*_*hop 10 ruby multithreading ruby-on-rails 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
Run Code Online (Sandbox Code Playgroud)

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

因为我对线程很新,所以我想知道我在这里做错了什么,或者它是否有可能完成我正在尝试做的事情,也就是说,在paralell中运行4个计算并将结果返回给客户端.

谢谢,

乔

Die*_*zar 12

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

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

threads = []
threads << Thread.new ...
Run Code Online (Sandbox Code Playgroud)

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

threads.each &:join
Run Code Online (Sandbox Code Playgroud)

如果你真的想确定这可以帮助你只是对整个行动进行基准测试:

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
Run Code Online (Sandbox Code Playgroud)

希望有所帮助.