マルチスレッドと例外

最近、「マルチスレッドプログラミング出来る?」と聞かれることが何度かありました。マルチスレッドプログラムはシングルスレッドなプログラムに比べて考える必要のあることが多く*1、プログラミングのコスト増加に比較してリターンが少ないため「基本的に使わない」(少なくとも性能の最適化という面では)というスタンスです。*2
試しに Ruby で複数の Web ページを取得するコードを書いてみました。引数のファイルか標準入力から http://〜 な URI を読み込んで、スレッドを生成してゲットします。


#!/usr/bin/env ruby

require 'net/http'

def remove_scheme(line)
line.sub(/\A.*:\/\//,'')
end

def 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"
end

threads = []
while line = ARGF.gets
line.chomp!.strip!
t = Thread.new(line) {
begin
get_http(line)
rescue
print "#{$!}\n"
end
}
threads.push(t)
end

threads.each {|t|
t.join
}

取得時に例外が発生する可能性を考えて例外補足をしています*3が、Ruby のリファレンスを見ると例外時の挙動は以下のように書いてあります。

あるスレッドで例外が発生し、そのスレッド内で rescue で捕捉されなかった場合、通常はそのスレッドだけがなにも警告なしに終了されます。

例外補足をしなかった場合、どうもスレッドじゃなくてインタプリタが終了しているような気がするのだけれど、何か勘違いしているんだろうか。

*1:グローバルメモリが共有されることや、デッドロックの問題

*2:使えない、とは意地でも言わない(笑

*3:Proxy が必要な環境でこれを動かすと SocketError が発生します