読者です 読者をやめる 読者になる 読者になる
無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

Thread#raise

Ruby

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みたいな動作になるイメージ)だと思っていたのだけど、こういうものなのか?