Thread#raise
Thread#raiseで、任意のスレッドで強制的に例外を発生させることが可能です。
- 例外なので、スレッド内で捕捉(catch)して処理を振り別けることができます。
- ensureブロックもちゃんと実行されます。
t = Thread.fork { begin p "start" i = 0 while true p i+=1 sleep 0.2 end p "end" # ここには来ない ensure p "ensure" end } sleep 1 t.raise RuntimeError, "stop." t.value #スレッド内で発生した例外がスローされる
実行結果です。
"start" 1 2 3 4 5 "ensure" C:/xxx/thread_raise.rb:17: stop. (RuntimeError) from C:/xxx/thread_raise.rb:18:in `value' from C:/xxx/thread_raise.rb:18
なるほど、これを使ってスレッドの安全な停止(ensureでの後始末が保証されるという意味で)ができるのかー、と思ったのだけど、Thread#killも同じ挙動になった・・・。
t = Thread.fork { begin p "start" i = 0 while true p i+=1 sleep 0.2 end p "end" # ここには来ない ensure p "ensure" end } sleep 1 #t.raise RuntimeError, "stop." t.kill t.value
実行結果です。ensureがちゃんと実行されています。ちなみに例外は発生しません。
"start" 1 2 3 4 5 "ensure"
killは呼び出された時点で強制終了(JavaのSystem#exitみたいな動作になるイメージ)だと思っていたのだけど、こういうものなのか?