【问题标题】:jRuby threading - am I doing it right?jRuby 线程 - 我做对了吗?
【发布时间】:2017-07-04 08:17:23
【问题描述】:

您介意告诉我我在 Ruby 中的线程是否正确吗?

我有一个数组items,我想在 16 个线程中处理它,等到所有线程都完成后,再做更多的工作。

这是我的代码;

    chunks = items.each_slice(items.count / 16).to_a
puts chunks.length

queue = Queue.new
semaphore = Mutex.new
threads = []

puts '[+] Building Queue'
chunks.each do |chunk|
    threads << Thread.new {
        chunk.each do |item|
            array = []
            metadata.each do |m|
                array << m.evaluate(item) rescue ''
            end
semaphore.synchronize {
    queue << array.join(20.chr)
}
        end
    }
end
puts '[+] Running threads'
threads.each{|t|t.join; puts 'Threads done'}

#Do more work here, queue should be fully populated
puts '[+] Writing to file'
File.open('E:/Export.dat', 'wt', encoding: 'UTF-16LE') do |f|
    until queue.empty?
        unit = queue.pop(true) rescue nil
        if unit
            f.puts unit
        end
    end
end

代码运行,但没有给我预期的线程性能,对吗?

谢谢

【问题讨论】:

  • 您的 ruby​​ 解释器是否允许在多个线程上运行?
  • 是的,我只是想确定我的代码逻辑是否合理
  • 您有多少 CPU 可用?
  • 逻辑没问题。这就是我问这个问题的原因。应该更快。
  • 你在哪里使用queue

标签: ruby multithreading jruby


【解决方案1】:

您不太可能看到性能改进,因为每个线程都在阻塞以将结果添加到队列中。 Queue 类是线程安全的,因此您不需要 Mutex 来保护它。

为了使多线程代码更好地工作,您希望每个线程尽可能独立地运行。下面的实现应该会提高性能。

chunks = items.each_slice(items.count / 16).to_a
puts chunks.length

queue = Queue.new
threads = []

puts '[+] Building Queue'
chunks.each do |chunk|
    threads << Thread.new do
        chunk.each do |item|
            array = []
            metadata.each do |m|
                array << m.evaluate(item) rescue ''
            end
            queue << array.join(20.chr)
        end
    end
end
puts '[+] Running threads'
threads.each{|t|t.join; puts 'Threads done'}

#Do more work here, queue should be fully populated
puts '[+] Writing to file'
File.open('E:/Export.dat', 'wt', encoding: 'UTF-16LE') do |f|
    until queue.empty?
        unit = queue.pop(true) rescue nil
        if unit
            f.puts unit
        end
    end
end

您还需要衡量代码中的瓶颈所在。简单的计时器(开始时间和结束时间之间的差异)很好。如果元数据的评估需要 10ms 的线程和 100ms 没有线程,写入文件需要 1000ms。那么你不会注意到与多线程有很大的不同。

【讨论】: