2012-10-20 83 views
3

我有一個Ruby腳本使用線程讀取HTML頁面通過HTTP:確定紅寶石線程狀態

require "thread" 
require "net/http" 

q = Queue.new 
q << "http://google.com/" 
q << "http://rubygems.org/" 
q << "http://twitter.com/" 
t = Thread.new do 
    loop do 
    html = Net::HTTP.get(URI(q.pop)) 
    p html.length 
    end 
end 

10.times do 
    puts t.status 
    sleep 0.3 
end 

我試圖確定而它取出由給定的源內容的線程的狀態。這是我得到的輸出:

run 
219 
sleep 
sleep 
7255 
sleep 
sleep 
sleep 
sleep 
sleep 
sleep 
65446 
sleep 

線程處於「休眠」狀態,幾乎所有的時間,雖然它的實際工作。我知道它正在等待HTTP類來檢索內容。最後一次「睡眠」是不同的:線程試圖從空隊列中彈出值並切換到「睡眠」狀態,直到隊列中有新的東西。

我希望能夠檢查線程中發生了什麼:它是在HTTP上工作還是等待新作業出現?

什麼是正確的做法?

+0

如果它回答你的問題,一定要接受一個答案。在最佳答案的編號下選擇複選標記。 – vacawama

回答

4

睡眠狀態似乎覆蓋了I/O等待和同步阻塞,所以您將無法使用線程狀態來知道您正在處理還是等待。相反,您可以使用線程的本地存儲來傳遞該線程。使用Thread#[]=來存儲一個值,並使用Thread#[]來取回它。

require "thread" 
require "net/http" 

q = Queue.new 
q << "http://google.com/" 
q << "http://rubygems.org/" 
q << "http://twitter.com/" 
t = Thread.new do 
    loop do 
    Thread.current[:status] = 'waiting' 
    request = q.pop 
    Thread.current[:status] = 'fetching' 
    html = Net::HTTP.get(URI(request)) 
    Thread.current[:status] = 'processing' 
    # Take half a second to process it. 
    Time.new.tap { |start_time| while Time.now - start_time < 0.5 ; end } 
    p html.length 
    end 
end 

10.times do 
    puts t[:status] 
    sleep 0.3 
end 

我已經添加了一個很短的循環來消磨時間。沒有它,你不太可能在輸出中看到「處理」:

219 
processing 
fetching 
processing 
7255 
fetching 
fetching 
fetching 
62471 
processing 
waiting 
waiting 
+0

感謝這個想法。我一直在想它,但是在線程代碼中創建自定義狀態並在它們之間切換看起來有些尷尬。我認爲應該有一些美麗的解決方案,不會出現在我的腦海中:) – Ivan