当每个元素都需要处理时,我有一个ruby脚本数组:
threads = []
elemets.each do |element|
threads.push(Thread.new{process(element)}}
end
threads.each { |aThread| aThread.join }
但是由于资源限制,如果一次不处理四个元素,脚本将以最佳方式工作。
不,我知道我可以转储每个循环并使用一个变量来计数4个元素,然后等待,但是有没有更凉爽的红宝石方法呢?
Answers:
您可以按4个一组枚举数组:
>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].each_slice(4) {|a| p a}
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11, 12]
所以你可以尝试像
elements.each_slice(4) do | batch |
batch.each do | element |
threads.push(Thread.new{process(element)}}
end
(do stuff to check to see if the threads are done, otherwise wait )
end
不过,它可能并不是您所需要的-自凌晨3点起,我已经起床,而且我只有几个小时的睡眠时间。:/
如果我没看错,您一次最多只能处理4个线程。
在我看来,您应该只启动4个线程,并从共享的Queue(标准线程库的一部分)中读取所有线程以处理元素。
当队列为空时,您可以使线程结束。
将数组切成4个相等的数组,并让每个线程处理1/4个元素,并假定每个元素在同一时间处理。如果某些线程比其他线程花费更长的时间,则您的某些线程将提早完成。
使用队列,直到共享队列为空,没有线程停止,因此我认为这是一种更有效的解决方案。
这是一个基于您的代码的工作程序,用于演示:
require 'thread'
elements = [1,2,3,4,5,6,7,8,9,10]
def process(element)
puts "working on #{element}"
sleep rand * 10
end
queue = Queue.new
elements.each{|e| queue << e }
threads = []
4.times do
threads << Thread.new do
while (e = queue.pop(true) rescue nil)
process(e)
end
end
end
threads.each {|t| t.join }
ArgumentError: tried to create Proc object without a block
似乎不喜欢while (e = queue.pop(true) rescue nil)
2.3.1
。我在Rails的rake任务中运行它,因此很可能在其他地方发生冲突。
在铁轨中可以使用更易读的形式 in_groups_of
arr= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
arr.in_groups_of(4, false) {|a| p a}
结果:
[1, 2, 3, 4]
[5, 6, 7, 8]
[9, 10, 11]
最后一行只有3个元素,因为我们在中指定了false in_group_of
。如果需要nil或其他任何值,则可以用该值替换false。
in_groups_of
是一种rails方法,不适用于普通红宝石
是的,但是您需要做一些方法重写。通常的方法是这样覆盖'/' Array
:
class Array
def / len
a = []
each_with_index do |x,i|
a << [] if i % len == 0
a.last << x
end
a
end
end
有了这个定义,您现在可以轻松地执行以下操作:
foo = [1,2,3,4,5,6]
foo / 2
# Result is [[1,2], [3,4], [5,6]]
/
不%
?如果另一位开发人员(或实施此操作的我)在一年或两年之内到来并想弄清楚代码,问“Array
数字除以数字到底意味着什么”怎么办?