具有消费者线程和作业队列的Ruby Sinatra

时间:2013-04-15 20:30:16

标签: ruby multithreading sinatra

我正在尝试创建一个非常简单的restful服务器。当它收到请求时,我想在队列上创建一个新作业,当前线程向客户端返回响应时,该作业可由另一个线程处理。

我看着西纳特拉,但还没走得太远。

require 'sinatra'
require 'thread'

queue = Queue.new

set :port, 9090

get '/' do
  queue << 'item'
  length = queue.size
  puts 'QUEUE LENGTH %d', length
  'Message Received'
end

consumer = Thread.new do
  5.times do |i|
    value = queue.pop(true) rescue nil
    puts "consumed #{value}"
  end
end

consumer.join

在上面的例子中,我知道消费者线程只会运行几次(而不是应用程序的生命周期),但即使这样也不适用于我。

有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

您的主要问题是致电Queue#pop。您正在传递true,这会导致暂停线程并引发异常,而是使用nil进行救援。因此,在任何其他事情发生之前,您的消费者线程会循环五次。

您需要将该行更改为

value = queue.pop

以便线程等待将新数据推送到队列中。

您还需要从结尾删除consumer.join行,因为一旦您将呼叫更改为pop,这将导致死锁。

(此外,它不是您主要问题的一部分,但在打印队列长度时,您似乎想要printf而不是puts