Ruby のスレッドを表現するクラスです。
Thread
を使うことで並行プログラミングが可能になります。スレッド
はメモリ空間を共有して同時に実行される制御の流れです。ただし、現在の実
装では Ruby インタプリタは時分割でスレッドを実行しますので、スレッドを
使うことで実行速度が速くなることはありません。
プログラムの開始と同時に生成されるスレッドをメインスレッド と呼 びます。なんらかの理由でメインスレッドが終了する時には、他の全てのスレッ ドもプログラム全体も終了します。ユーザからの割込みによって発生した例外 はメインスレッドに送られます。
スレッドの起動時に指定したブロックの実行が終了するとスレッドの実行も終 了します。ブロックの終了は正常な終了も例外などによる異常終了も含みます。
Ruby のスレッドスケジューリングは優先順位付のラウンドロビンです。一定 時間毎、あるいは実行中のスレッドが権利を放棄したタイミングでスケジュー リングが行われ、その時点で実行可能なスレッドのうち最も優先順位が高いも のにコンテキストが移ります。
あるスレッドで例外が発生し、そのスレッド内で rescue で捕捉されなかっ
た場合、通常はそのスレッドだけがなにも警告なしに終了されます。ただ
しその例外で終了するスレッドを Thread#join
で待っている他の
スレッドがある場合、その待っているスレッドに対して、同じ例外が再度
発生します。
begin t = Thread.new do Thread.pass # メインスレッドが確実にjoinするように raise "unhandled exception" end t.join rescue p $! # => "unhandled exception" end
また、以下の 3 つの方法により、いずれかのスレッドが例外によって終 了した時に、インタプリタ全体を中断させるように指定することができま す。
上記3つのいずれかが設定されていた場合、インタプリタ全体が中断されます。
個々のスレッドは、以下の実行状態を持ちます。これらの状態は Object#inspect や Thread#status によって見ることができます。
p Thread.new {sleep 1} # => #<Thread:0xa039de0 sleep>
生成されたばかりのスレッドや run や wakeup で起こされたスレッドはこの状態です。 join でスレッドの終了を待っているスレッドもスレッドの 終了によりこの状態になります。
この状態のスレッドは「生きて」います。
Thread.stop や join により停止されたスレッ ドはこの状態になります。
この状態のスレッドは「生きて」います。
kill 等で終了されるスレッドは一時的にこの状態になりま す。この状態から停止状態(stop)になることもあります。
この状態のスレッドはまだ「生きて」います。
kill 等で終了したスレッドはこの状態になります。この状 態のスレッドはどこからも参照されていなければ GC によりメモリ上から なくなります。
この状態のスレッドは「死んで」います。
Thread.abort_on_exception
Thread.abort_on_exception = newstate
真の時は、いずれかのスレッドが例外によって終了した時に、インタプリタ 全体を中断させます。デフォルトは偽、すなわち、通常あるスレッドで起こった例 外は、Thread#join などで検出されない限りそのスレッ ドだけをなにも警告を出さずに終了させます。スレッドと例外に詳述。
参照の場合は真偽値を、代入形式では右辺 newstate を、返します。
Thread.critical
Thread.critical = newstate
真である間、スレッドの切替えを行いません。カレントスレッドが停止
(stop)した場合やシグナルに割り込まれた場合には、自動的に
false
になります。
ただし、Thread.new によりスレッドを生成した場合にはそ のスレッドは実行されます。また、Thread.pass により明 示的に切替えることもできます。
参照の場合は真偽値を、代入形式では右辺 newstate を、返します。
注意: I/O や GC、拡張ライブラリがからむとこのフラグは無視さ れることもあります。排他制御を行うにはこのメソッドに頼らず Mutex や Monitor を使うべきです。
Thread.current
現在実行中のスレッド(カレントスレッド)を返します。
Thread.exit
カレントスレッドの実行を終了します。
カレントスレッドを返します。
カレントスレッドが唯一のスレッドであるなら、exit(0) により終了します。
Thread.kill(thread)
指定したスレッドの実行を終了させます。既に終了しているスレッドに対 しては何もしません。
thread を返します。*2
Thread.list
生きているスレッドのうち、実行中(run)または停止中(stop)のスレッド の配列を返します。 *3
Thread.main
メインスレッドを返します。
Thread.new([arg, ...]) { ... }
Thread.start([arg, ...]) { ... }
Thread.fork([arg, ...]) { ... }
スレッドを生成して、ブロックの評価を開始します。
引数はそのままブロックに渡されます。スレッドの開始と同時にその スレッド固有のローカル変数に値を渡すために使用します。
生成したスレッドを返します。
例えば、以下のコードは間違いです。スレッドの実行が開始される前に 変数 i が書き変わる可能性があるからです。
for i in 1..5 Thread.start { p i } end
上の例は以下のように書き直すべきです。
for i in 1..5 Thread.start(i) {|t| p t } end
Thread.pass
他のスレッドに実行権を譲ります。実行中のスレッドの状態を変えずに、 他の実行可能状態のスレッドに制御を移します(明示的なスケジューリン グ)。
nil
を返します。
Thread.stop
他のスレッドから run メソッドで再起動されるまで、カレ ントスレッドの実行を停止します。
nil
を返します。
self[name]
name に対応したスレッドに固有のデータを取り出しま す。name は文字列か Symbol で指定します。
name に対応するスレッド固有データがなければ nil
を返し
ます。
self[name] = val
val を name に対応するスレッド固有のデータとして格納し
ます。name は文字列か Symbol で指定します。
val に nil
を指定するとそのスレッド固有データは削除さ
れます。
val を返します。
abort_on_exception
abort_on_exception = newstate
参照の場合は真偽値を、代入形式では右辺 newstate を、返します。
真の時は、そのスレッドが例外によって終了した時に、インタプリタ 全体を中断させます。デフォルトは偽です。スレッドと例外に詳述。
alive?
スレッドが「生きている」時、true
を返します。
Thread#status が真を返すなら、このメソッドも真 です。
exit
kill
terminate ((<ruby 1.7 feature>))
スレッドの実行を終了させます。
self
を返します。
group ((<ruby 1.8 feature>))
スレッドが属している ThreadGroup オブジェクトを返します。
p Thread.current.group == ThreadGroup::Default # => true
死んでいるスレッドは nil を返します。
join
join(limit) ((<ruby 1.7 feature>))
スレッド self
の実行が終了するまで、カレントスレッドを停止し
ます。self
が例外により終了していれば、その例外がカレントス
レッドに対して発生します。
self
を返します。
ruby 1.7 feature: 引数 limit を指定すると、limit 秒でタイム
アウトし、nil
を返します。
以下は、生成したすべてのスレッドの終了を待つ例です。
threads = [] threads.push(Thread.new { n = rand(5); sleep n; n }) threads.push(Thread.new { n = rand(5); sleep n; n }) threads.push(Thread.new { n = rand(5); sleep n; n }) threads.each {|t| t.join}
key?(name)
name に対応したスレッドに固有のデータが定義されていれば
true
を返します。name は文字列か Symbol で指定し
ます。
keys ((<ruby 1.7 feature>))
スレッド固有データに関連づけられたキーの配列を返します。キーは Symbol で返されます。
th = Thread.current th[:foo] = 'FOO' th['bar'] = 'BAR' p th.keys #=> [:bar, :foo]
priority
スレッドの優先度を返します。優先度のデフォルト値は 0 で、この値の 大きいスレッドは小さいスレッドよりも優先度が高くなります。
priority = val
スレッドの優先度を設定します。負の値も指定できます。
val
を返します。
*4
raise([error_type,][message][,traceback])
そのスレッドで強制的に例外を発生させます。
引数の意味については組み込み関数 raise を参照してく ださい。
Thread.new { sleep 1 Thread.main.raise "foobar" } begin sleep rescue p $!, $@ end => #<RuntimeError: foobar> ["-:3"]
run
停止状態(stop)のスレッドを再開させます。 Thread#wakeup と異なりすぐにスレッドの切り替え を行います。死んでいるスレッドに対して実行すると ThreadError が発生します。
self
を返します。
safe_level
self
のセーフレベルを返します。カレントスレッドの
safe_level
は、$SAFE と同じです。
セーフレベルについてはセキュリティモデルを参照してください。
status
生きているスレッドの状態を文字列 "run"、"sleep", "aborting" のいず
れかで返します。正常終了したスレッドに対して false
、例外によ
り終了したスレッドに対して nil
を返します。
*5
Thread#alive? が真を返すなら、このメソッドも真です。
stop?
スレッドが終了(dead)あるいは停止(stop)している時、true
を返
します。
value
スレッド self
が終了するまで待ち(join と同じ)、
そのスレッドのブロックが返した値を返します。スレッド実行中に例外が
発生した場合には、その例外を再発生させます。
以下は、生成したすべてのスレッドの終了を待ち結果を出力する例です。
threads = [] threads.push(Thread.new { n = rand(5); sleep n; n }) threads.push(Thread.new { n = rand(5); sleep n; n }) threads.push(Thread.new { n = rand(5); sleep n; n }) threads.each {|t| p t.value}
最後の行で、待ち合わせを行っていることがわかりにくいと思うなら以下 のように書くこともできます。
threads.each {|t| p t.join.value}
wakeup
停止状態(stop)のスレッドを実行可能状態(run)にします。死んでいるス レッドに対して実行すると ThreadError が発生します。
self
を返します。
*1あらい 2001-10-14:
p (Thread.new { Thread.exit }.value)
は、false を表示します。Thread.exit や Thread#kill ではス
レッドの終了結果を設定していないためです
[ruby-dev:14904]
*2exit と同様 Thread の終了結果を設定しません
*3ruby 1.7 feature: version 1.7 では、aborting 状態であるスレッド
も要素に含まれます。つまり「生きている」スレッドの配列を返します
*4ruby 1.6 feature: version 1.6.5 までは self
を返し
ていました
*5ruby 1.6 feature: version 1.6.5 までは、終了処理中
(aborting)のスレッドに対しては "run" を返していました