ruby数组元素在四个组中的工作
每个元素需要处理时,我有一个ruby脚本数组:
threads = [] elemets.each do |element| threads.push(Thread.new{process(element)}} end threads.each { |aThread| aThread.join }
由于资源的限制,如果不再处理四个元素,脚本将以最佳方式工作。
不,我知道我可以转储每个循环,并使用一个variables来计算4个元素,然后等待,但有一个更酷的ruby的方式来做到这一点?
您可以枚举数组为4:
>> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12].each_slice(4) {|a| pa} [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个线程,并让他们都从一个共享的队列(标准线程库的一部分)读取来处理元素。
当队列为空时,可以让线程结束。
将数组切成4个相等的数组,每个线程处理1/4个元素,假定每个元素在同一时间处理。 如果有些人比别人花更长的时间,你的一些线程将提前结束。
使用一个队列,线程停止,直到共享队列是空的,所以这是一个更有效的解决scheme。
这是一个基于你的代码的工作程序来演示:
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 }
是的,但是你需要做一些重写的方法。 通常的做法是覆盖“/”像这样的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]]
不知道是否下面的变种算作只是使用“variables来计数4个元素”,或者可以被认为是很酷,但它给你一个大小不超过4个元素的切片数组:
x = (1..10).to_a 0.step(x.size - 1, 4) do |i| # Choose one p x.slice(i, 4) px[i, 4] end