我需要從Rails應用程序收集一些數據,將其聚合並定期將其發送到遠程服務器。我在application.rb中實例化了一個全局變量中的聚合類(我知道,我知道)。Rails中的後臺線程無法看到實例變量
在我的聚合類中,我啓動了睡眠10秒的線程,然後查看隊列,處理數據併發送它。隊列是存儲在類的實例變量中的哈希。
從rails控制器中,我調用aggregator類中的一個方法將數據排列在散列中。當然,這與讀取隊列的後臺任務不同。問題是後臺任務從未看到散列中的任何數據。在我的日誌中,我寫出哈希的object_id(從控制器線程寫入),以及從背景線程讀取哈希時的object_id。 hash#object_id匹配兩個線程,但後臺線程從不會看到數據。
什麼查殺我就是這個工作正常軌道外。我已經建立了許多線程的測試,真正的重擊它,它工作正常(有一些線程保護,我沒有顯示爲清晰)。任何人都知道object_id
的匹配程度如何,但內容不一致?
class Aggregator
def initialize
@q = {}
@timer = nil
end
def start
@timer = Thread.new do
loop do
sleep(10)
flush_q
end
end
end
def flush_q
logger.debug "flush: q.object_id = #{@q.object_id}" # matches what I get below
logger.debug "flush: q.length = #{@q.length}" # always zero!
@q.each_pair do |k,v|
# pack it up and send it
end
@q.clear
end
def add(item)
logger.debug "add: q.object_id = #{@q.object_id}" # matches what I get above
@q[item.name] ||= item
logger.debug "add: q.length = #{@q.length}" # increases with each add
# not actually that simple, but not relevant
end
end
你是怎麼調用'start'和'add'? –
'start'在創建此類的單個實例後被調用一次。 'add'從軌道控制器被調用。 – Daiku
嗯,我注意到的第一件事是你沒有任何互斥體同步,這意味着對線程的訪問不受線程控制,這可能是有問題的。在哪裏定義了聚合器實例? –