2010-01-01 40 views
60

组我有一个Ruby脚本阵列时,每个元素都需要处理:红宝石的数组元素的工作在四个

threads = [] 
elemets.each do |element| 
    threads.push(Thread.new{process(element)}} 
end 
threads.each { |aThread| aThread.join } 

怎么过,由于资源限制,脚本以最佳的方式工作,如果没有更多的四个元素一次被处理。

没有,我知道我可以转储每个回路,并使用一个变量来计算4个元素,然后等待 但有一个冷却器红宝石办法做到这一点?

回答

122

您可以在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点起就已经起床了,而且我只睡了几个小时。 :/

+0

@Rilindo:这太棒了!修改了两行,我很乐意去。谢谢。当任务需要可变时间进行处理时,以下 – Eli 2010-01-01 11:17:07

+1

(my)解决方案应该更高效。此解决方案假定每个线程将花费相同的时间来处理4个元素的列表。 – 2012-07-22 19:57:55

+2

我想我只是爱上了Ruby再次:) – superluminary 2012-09-12 11:26:55

2

不知道刚才使用下面的变种数“变量来计算4个元素”,或可考虑很酷,但它给你的尺寸的片不大于4个元素的数组:

x = (1..10).to_a 
0.step(x.size - 1, 4) do |i| 
    # Choose one 
    p x.slice(i, 4) 
    p x[i, 4] 
end 
2

是的,但你需要做一些方法覆盖。通常的做法是重写“/”为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]] 
+1

我认为首要的这样的基本类的方法是相当危险的 - 即使(如在这种情况下),他们之前没有定义。为什么它是'/'而不是'%'?如果另一位开发人员(或者我,实现了这个)在一两年内来到并希望理解代码,问“数组除了数字究竟意味着什么”实际上意味着什么? – haslo 2015-01-26 14:06:27

19

如果我正确地读了你,你一次只想处理不超过4个线程。

对我来说听起来你应该只启动4个线程,并让它们都从共享队列(标准线程库的一部分)读取以处理元素。

当队列为空时,可以让线程结束。

将数组切成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 }