3

スレッドを使用してHTTP経由でHTMLページをフェッチするRubyスクリプトがあります。

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で動作しているのか、それとも単に新しいジョブが表示されるのを待っているのか。

それを行う正しい方法は何ですか?

4

1 に答える 1

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
于 2012-10-20T18:47:59.973 に答える