2013-04-15 21 views
1

我试图创建一个非常简单宁静的服务器。当它接收到请求时,我想在当前线程返回对客户端的响应时由另一个线程处理的队列上创建新作业。红宝石西纳特拉与消费者线程和作业队列

我看着西纳特拉,但没有得到太远。

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 

在上面的例子中,我知道消费者线程将只运行了几次(相对于应用程序的生命),但即使这不是为我工作。

有没有更好的方法?

回答

4

你的主要问题是你要Queue#pop电话。你传递true,这导致它挂起线程并抛出一个异常,这样你们用nil抢救。因此,在任何其他事情发生之前,您的消费者线程会循环五次。

你需要该行更改为

value = queue.pop 

,这样被推到队列中的新数据的线程等待。

您还需要从最后删除consumer.join行,因为一旦将呼叫更改为pop,会导致死锁。 (另外,它不是你主要问题的一部分,但是当你打印队列长度时,它看起来像你想要的printf而不是puts)。

+0

非常感谢,完美的作品给了我一些建设。干杯 – Dave

+1

另一个小问题,$ stderr.puts应该用于在线程环境中输出调试语句。标准输出(puts,$ stdout.puts等)可能实际上不按照正确的顺序打印,这取决于可能非常令人沮丧的实现。这是因为标准输出通常以非线程友好的方式进行缓冲。标准错误很少被缓冲(即使在内核级别,我认为它甚至可能是不缓冲标准错误的标准)。此建议适用于所有编程语言和环境。 – seo

相关问题