在Ruby中使用限制进行线程化

时间:2009-11-08 18:52:47

标签: ruby multithreading queue

我有一个我需要执行的任务,do_stuff(opts),每个需要约1秒,即使其中1到10个并行运行。我需要在最后为每个操作收集一系列结果。

如果我有30个要做的事情,我将如何有效地使用线程来排队do_stuff(opts)操作,因此不会超过10个并发运行,但结果数组不会给出/打印/等等(30)任务已经完成?

我通常至少有一些代码试图说明我的意思,但是使用线程我有点亏本!提前致谢

6 个答案:

答案 0 :(得分:4)

我不知道它对于一个更复杂的应用程序有多好用,但我发现这样的东西可以很好地用于macruby的简单线程场景。

thread_limit = 4

threads = []
things_to_process.each do |thing|
  until threads.map { |t| t.status }.count("run") < thread_limit do sleep 5 end
  threads << Thread.new { the_task(thing) }
end
output = threads.map { |t| t.value }

until循环等待,直到少于指定数量的已创建线程运行,然后允许执行主线程继续启动下一个线程。

将为输出变量分配一个由the_task返回的值的数组,其排序对应于输入数组things_to_process。主线程将阻塞,直到每个创建的线程都返回一个值。

答案 1 :(得分:2)

您需要实施this pattern
This question讨论了如何在Ruby中完成这项工作

答案 2 :(得分:1)

如果你真的在表演之后,你可能还想看看jruby 它使用实际的OS线程而不是其他ruby实现使用的绿色线程

答案 3 :(得分:1)

此解决方案收集$ results数组的结果。它允许&#39; thread_limit&#39;要创建的线程,然后在创建之前等待它们完成。

   $results = []

   def do_stuff(opts={})
     'done'
   end

   def thread_wait(threads)
     threads.each{|t| t.join}
     threads.each {|t| $results << t }
     threads.delete_if {|t| t.status == false}
     threads.delete_if {|t| t.status.nil? }
   end

   opts = {}
   thread_limit = 20
   threads = []
   records.each do |r|
     thread_wait(threads) while threads.length >= thread_limit
     t = Thread.new { do_stuff(opts) }
     t.abort_on_exception = true
     threads << t
   end
   # Ensure remaining threads complete
   threads.each{|t| t.join}

答案 4 :(得分:0)

另外,如果您不熟悉Ruby线程,请查看this教程。

答案 5 :(得分:0)

我使用paralsparalsmap

def parals(objects, n: 50)
  objects.shuffle.each_slice(n).map do |g|
    print '{'
    threads = []
    g.map { |i| threads << Thread.new(i) { |i| yield(i) } }
    threads.each(&:join)
    print '}'
  end
end

def paralsmap(objects, n: 50)
  res = []

  objects.each_slice(n).map do |g|
    print '{'
    threads = []
    g.map { |i| threads << Thread.new(i, res) { |i| res << yield(i) } }
    threads.each(&:join)
    print '}'
  end

  res
end

e.g:

parals((0..100).to_a) { |i| puts i }
urls = parals((0..100).to_a) { |i| "https://google.com/?q=#{i}" }

您可以使用n参数来限制线程数。