如何多次fork,运行异步并一次处理所有结果?

时间:2013-01-20 17:11:25

标签: ruby process fork

我有以下代码:

data_set = [1,2,3,4,5,6]

results  = []

data_set.each do |ds|
  puts "Before fork #{ds}"
  r,w = IO.pipe
  if pid = Process.fork
    w.close
    child_result = r.read
    results << child_result
  else
    puts "Child worker for #{ds}"
    sleep(ds * 5)
    r.close
    w.write(ds * 2)
    exit
  end
end

Process.waitall
puts "Ended everything #{results}"

基本上,我希望每个孩子都做一些工作,然后将结果传递给父母。我的代码现在并不是并行运行,我不知道我的问题到底在哪里,可能是因为我在父母那里读书,但我不确定。我需要做什么才能让它运行异步?

编辑:我将代码更改为此,似乎工作正常。我有没有看到任何问题?

data_set = [1,2,3,4,5,6]

child_pipes = []
results     = []

data_set.each do |ds|
  puts "Before fork #{ds}"
  r,w = IO.pipe
  if pid = Process.fork
    w.close
    child_pipes << r
  else
    puts "Child worker for #{ds}"
    sleep(ds * 5)
    r.close
    w.write(ds * 2)
    exit
  end
end

Process.waitall
puts child_pipes.map(&:read)

1 个答案:

答案 0 :(得分:0)

如果孩子的输出大于管道容量,则孩子可能block writing to the pipe到父母。{}理想情况下,父节点将在子管道上执行选择循环,或者从子管道中生成读取线程,以便在可用时使用数据,以防止子节点在完整管道上停顿并失败。实际上,如果子输出很小,只需执行waitall和读取即可。

其他人已经以可重用的方式解决了这些问题,您可以尝试使用parallel gem来避免编写一堆不必要的代码。