2012-10-20 78 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