Ruby中的线程化和循环

时间:2014-12-08 19:43:25

标签: ruby arrays multithreading

我正在寻找一种方法让我的线程迭代一堆电子邮件地址而不必踩到彼此的脚趾并更改变量(我不能使用互斥锁)。我找到了一些关于使用"线程局部变量的信息"但似乎无法让它发挥作用。下面是我的问题的一个例子(这只是代码的一小部分)。

(1..(threads).map { |thread_count|

  Thread.new do

    (1..(messages).each do |message_count|

    email = recipients_array[recipient_count].join(", ") 

    if (recipient_count != ( recipients_array.length - 1 ))
      recipient_count += 1
    else
      recipient_count = 0
    end

我已经坚持了一段时间。我编写的脚本在JRuby中使用多线程来发送电子邮件。我告诉脚本我想发送多少个线程以及我要发送的每个线程的消息数量。我传入一个收件人地址的文本文件,我加载到一个数组中。然后我想遍历数组,以便:

  • 主题1,消息1将转到电子邮件1
  • 主题2,消息1将转到电子邮件1
  • 主题1,消息2将转到电子邮件2
  • 主题2,消息2将转到电子邮件2

依旧......它开始很好但是如果我设置做5个线程x 5个消息:

  • 主题1到5,消息1将转到电子邮件1
  • 主题1,消息2将转到电子邮件6

因为他们都访问了recipient_count变量并将其递增+1。

寻找有关如何更好地设置它的一些建议。

2 个答案:

答案 0 :(得分:0)

通常我会这样使用ruby多线程:

require 'thread'

count  = 4
result = []

mutex  = Mutex.new
queue  = Queue.new

# fill the queue
(0..100).each do |i|
  queue << i
end

(0..count).map do
  begin
    loop do
      item = queue.pop(true)
      item = do_something_with_it(item)

      mutex.synchronize do
        result << item
      end
    end
  rescue ThreadError
    Thread.exit
  end
end.each(&:join)

# process results

答案 1 :(得分:0)

您说这个脚本是以threadsmessagesrecipient_array作为参数调用的。我不确定recipients_array中的单个条目的形式是什么,Array#join是什么形式,也不确定当recipient_count达到最后一个索引recipients_array时为什么将其重置为0 {1}}。我假设有一些丢失的代码。但是,这个怎么样。

emails_handled = []
(0..threads - 1).map do |i|
  Thread.new do
    (i..messages * threads - 1).step(threads) do |n|
      email = recipients_array[n].join(", ")
      emails_handled[n] = 1
      # ... do stuff with your email
    end
  end
end
  • 每个线程都有相同的步骤和相同的端点,但起点不同,因此它们不会发生冲突。这不是最佳选择,但我自己也很擅长线程。
  • 如果您想获得recipient_count,可以致电emails_handled.compact.reduce(:+)。我不确定您是否需要recipient_countrecipients_array[]查询以外的任何内容 - 如果不是,您可以完全转储emails_handled