マルチスレッドと例外
最近、「マルチスレッドプログラミング出来る?」と聞かれることが何度かありました。マルチスレッドプログラムはシングルスレッドなプログラムに比べて考える必要のあることが多く*1、プログラミングのコスト増加に比較してリターンが少ないため「基本的に使わない」(少なくとも性能の最適化という面では)というスタンスです。*2
試しに Ruby で複数の Web ページを取得するコードを書いてみました。引数のファイルか標準入力から http://〜 な URI を読み込んで、スレッドを生成してゲットします。
取得時に例外が発生する可能性を考えて例外補足をしています*3が、Ruby のリファレンスを見ると例外時の挙動は以下のように書いてあります。
#!/usr/bin/env rubyrequire 'net/http'
def remove_scheme(line)
line.sub(/\A.*:\/\//,'')
enddef get_http(line)
reg = /\/[^\/]+\Z/o
uri = remove_scheme(line)
res = Net::HTTP.get_response(uri.sub(reg,''),uri.slice(reg))
print "Get:#{line} -- #{res.code}\n"
endthreads = []
while line = ARGF.gets
line.chomp!.strip!
t = Thread.new(line) {
begin
get_http(line)
rescue
print "#{$!}\n"
end
}
threads.push(t)
endthreads.each {|t|
t.join
}
あるスレッドで例外が発生し、そのスレッド内で rescue で捕捉されなかった場合、通常はそのスレッドだけがなにも警告なしに終了されます。
例外補足をしなかった場合、どうもスレッドじゃなくてインタプリタが終了しているような気がするのだけれど、何か勘違いしているんだろうか。