2013-04-15 19 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

相關問題