我有一个我需要执行的任务,do_stuff(opts)
,每个需要约1秒,即使其中1到10个并行运行。我需要在最后为每个操作收集一系列结果。
如果我有30个要做的事情,我将如何有效地使用线程来排队do_stuff(opts)
操作,因此不会超过10个并发运行,但结果数组不会给出/打印/等等(30)任务已经完成?
我通常至少有一些代码试图说明我的意思,但是使用线程我有点亏本!提前致谢
答案 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)
我使用parals
和paralsmap
:
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
参数来限制线程数。