Web リクエスト ハンドラー内からスレッドを起動すると、サーバーが実行されている限りスレッドは実行され続けますか?
Thread.joinと同様に、メイン スレッドをブロックしますが、join を呼び出して、すべてのスレッドを独自のスケジュールで完了させることはできませんか? Web 要求ハンドラーがブラウザーに HTTP 応答を返した後かもしれません。
Web リクエスト ハンドラー内からスレッドを起動すると、サーバーが実行されている限りスレッドは実行され続けますか?
Thread.joinと同様に、メイン スレッドをブロックしますが、join を呼び出して、すべてのスレッドを独自のスケジュールで完了させることはできませんか? Web 要求ハンドラーがブラウザーに HTTP 応答を返した後かもしれません。
次のコードは私にとっては問題なく動作します。OS X ローカル マシンでテストしたところ、1500 以上のリアル スレッドがシンおよびルビー 1.9.2 で実行されました。Heroku cedar スタックでは、スレッドの作成時にエラーが発生する前に、約 230 のスレッドを実行できます。
どちらの場合も、すべてのスレッドが想定どおりに終了したように見えます - 起動してから 2 分後です。「/」は Heroku で約 60 ミリ秒でレンダリングされ、その後 20 個のスレッドがそれぞれ 2 分間実行されます。
/ を数回更新してから数分待つと、スレッドが終了していることがわかります。私が 2 分間テストした理由は、heroku には応答に 30 秒の制限があり、それ以上の時間がかかると切断されるためです。しかし、これはバックグラウンド スレッドには影響しないようです。
$threadsLaunched = 0
$$threadsDone = 0
get '/' do
puts "#{Thread.list.size} threads"
for i in 1..20 do
$threadsLaunched = $threadsLaunched + 1
puts "Creating thread #{i}"
Thread.new(i) do |j|
sleep 120
puts "Thread #{j} done"
$threadsDone = $threadsDone + 1
end
end
puts "#{Thread.list.size} threads"
erb :home
end
(ホーム.erb)
<div id="content">
<h1> Threads launched <%= $threadsLaunched.to_s %> </h1>
<h1> Threads running <%= Thread.list.count.to_s %> </h1>
<h1> Threads done <%= $threadsDone.to_s %> </h1>
</div> <!-- id="content" -->
メインスレッドが終了すると、他のすべてのスレッドも強制的に破棄され、プロセスが終了します。
Thread.new do
# this thread never exists on its own
while true do
puts "."
sleep 1
end
end
sleep 5
この例に従うと、メインスレッドが終了すると、印刷スレッドもその作業を「完了」せずに終了します。join
メインスレッドを終了する前に、すべてのバックグラウンドスレッドが完了するのを明示的に待機する必要があります。
一方、メインスレッドが実行されている限り、他のスレッドは必要なだけ実行できます。要求/応答サイクルに任意の制限はありません。ただし、「元の」ルビーでは、スレッドは実際には同時ではなく、GILの対象であることに注意してください。真の並行性が必要な場合(異なるスレッドでコンピューター上で複数のコアを使用する場合)、真の並行スレッドを提供するJRubyまたはRubinius(2.0プレビュー)のいずれかを確認する必要があります。
後で処理するために要求サイクルから物事を取り出したいだけの場合は、1.8のグリーンスレッドと1.9のOSネイティブだがGILedのスレッドで十分です。より高いスケーラビリティが必要な場合は、バックグラウンドジョブに永続ワーカーを導入するdelayed_jobやResqueなどのテクノロジーを確認する必要があります。