你如何保持红宝石线活着

时间:2017-10-19 21:53:46

标签: ruby multithreading

运行此

# in initialize
@queue = Queue.new

@threads = Array.new(NUM_THREADS) do
    Thread.new do
      until @queue.empty?
        puts @queue.shift
      end
    end
  end

# later in another method, calling
@threads.each { |t| puts t.alive? } # puts false
@queue.push('something else')
# new item is not processed by thread

如何保持Ruby线程处于活动状态,以便它可以继续接收队列中的内容?

2 个答案:

答案 0 :(得分:0)

问题是在向队列添加任何内容之前初始化线程。线程在@queue.push行运行之前开始并消亡。

如果要保持线程的活动,即使队列中没有任何内容,您也可以更改线程的逻辑,使其永远循环:

Thread.new do
  loop do
    if val = @queue.shift
      puts val
    end
  end
end

你可以通过在线程循环中调用sleep来减少CPU消耗,比如每次迭代睡眠时间为0.1秒,因此每秒最多可以处理10个项目。例如,在我的Ruby REPL中运行以下内容会将进程的CPU消耗从0%提高到25%(这是非常高的)

 100.times { Thread.new { loop { } } }

但以下使用不到1%:

 100.times { Thread.new { loop { sleep 0.1 } } }

除了在其中添加任意sleep个数字之外,还有其他方法可以管理后台进程的CPU消耗:例如eventmachineresquesidekiq

答案 1 :(得分:0)

您可能想使用Ruby核心库中的Queue

方法popdeqshift可用于从队列中检索数据。 根据文档,使用这些方法

  

如果队列为空,则调用线程被挂起,直到数据为空   推入队列。

使用Queue,您的代码段看起来像这样

@queue = Queue.new

@threads = Array.new(NUM_THREADS) do
    Thread.new do
      while (item = @queue.shift)
        puts item
      end
    end
  end

# later in another method
@threads.each { |t| puts t.alive? } # true
@queue.push('something else') # is printed out

Queue#shift保持线程等待,直到将某些内容推入队列为止。您仍然需要循环,以便在处理完该项目后,线程将保持活动,挂起状态,等待下一个项目。