问题
I’m trying to create a very simple restful server. When it receives a request, I want to create a new job on a queue that can be handled by another thread while the current thread returns a response to the client.
I looked at Sinatra, but haven't got too far.
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
In the above example, I know the consumer thread would only run a few times (as opposed to the life of the application), but even this isn't working for me.
Is there a better approach?
回答1:
Your main problem is your call to Queue#pop. You’re passing true
, which causes it not to suspend the thread and raises an exception instead, which you rescue with nil
. Your consumer thread therefore loops five times before any thing else can happen.
You need to change that line to
value = queue.pop
so that the thread waits for new data being pushed onto the queue.
You’ll also need to remove the consumer.join
line from the end, since that will cause deadlock once you’ve changed the call to pop
.
(Also, it’s not part of your main problem, but it looks like you want printf rather than puts
when you print the queue length).
来源:https://stackoverflow.com/questions/16024197/ruby-sinatra-with-consumer-thread-and-job-queue