2010-01-01 63 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 }