Ruby并行each循环

12

我有以下代码:

FTP ... do |ftp| 
  files.each do |file| 
  ...
  ftp.put(file)
  sleep 1
  end 
end 

我希望能以单独的线程或并行的方式运行每个文件。正确的方法是什么?这样做是否正确?

这是我在并行宝石上的尝试。

FTP ... do |ftp| 
  Parallel.map(files) do |file| 
  ...
  ftp.put(file)
  sleep 1
  end 
end 

使用并行处理时可能会出现同时进行的输入/输出,如下所示:

as = [1,2,3,4,5,6,7,8]
results = Parallel.map(as) do |a|
  puts a
end

我该如何强制使用puts函数来按正常的行分隔方式输出内容?


通常我使用threach,它使用SizedQueues,因此允许您同时执行最大数量的并行作业(peach也可以)。 - mdesantis
我刚试了一下parallel,但还不确定它是否正常工作。 - Sten Kin
并行似乎很不错,我不知道它,谢谢。 - mdesantis
2个回答

5

并行化的整个关键在于同时运行。但是,如果您希望运行某个过程的部分代码按顺序运行,可以使用 mutex ,例如:

semaphore = Mutex.new
as = [1,2,3,4,5,6,7,8]
results = Parallel.map(as, in_threads: 3) do |a|
  # Parallel stuff
  sleep rand
  semaphore.synchronize {
    # Sequential stuff
    puts a
  }
  # Parallel stuff
  sleep rand
end

你会发现它可以正确打印输出,但不一定按照相同的顺序。我使用了in_threads而不是默认的in_processes,因为Mutex无法与进程一起使用。如果确实需要进程,请参见下面的替代方法。 参考资料:

0
为了保持简单,这里是我使用内置的Thread会做的事情:
results = files.map do |file|
  result = Thread.new do
    ftp.put(file)
  end
end

请注意,此代码假定ftp.put(file)可以安全返回。如果不能保证,您就必须通过将调用包装在超时块中,并使每个线程在抛出异常时返回异常,然后在循环的最后一个阶段进行阻塞检查,以查看results不包含任何异常来自己完成这一点。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接