Ruby のスレッドをバンバン起動したい。
起動前に現在の実行本数を調べたり、Queue.push したりするの面倒すぎるので、もっと単純に制御したいとおもっていて、Threadにモンキーパッチを当てる方法が思いついた。
同時実行数を指定したスレッド化
#!/usr/bin/env ruby # coding : utf-8 #スレッド条件を制限したい class << Thread alias_method :original_new, :new def Thread.new(*args, &block) if Thread.main[:max_concurrent] and Thread.main[:max_concurrent] > 0 then while(Thread.list.size >= Thread.main[:max_concurrent]) do Thread.pass end end puts "start" Thread.original_new(args,&block) end def Thread.max_concurrent=(num) Thread.main[:max_concurrent]=num end end Thread.max_concurrent=5 threads = [] threads << Thread.new{|t|sleep 1} threads << Thread.new{|t|sleep 1} threads << Thread.new{|t|sleep 1} threads << Thread.new{|t|sleep 1} threads << Thread.new{|t|sleep 1} threads << Thread.new{|t|sleep 1} threads << Thread.new{|t|sleep 1} threads.each{|t| t.join } puts :end
スレッド同時実行数の制御をすると何が嬉しいか
コマンドの大量起動とか便利じゃないですか?
./my_ruby_script *.jpg
などと、大量に画像を受け取って処理をする時に、Ruby側で処理をします。bashだと同時起動しないし。rubyですね。。やっぱ
他の方法だと面倒だ
- 逐次処理していると遅い
- とりあえず全部スレッド化すると重い
- キュー使うコードは面倒
というわけで、なんか良い解決法を探してたら冒頭のやり方に行き着いた
一つ一つファイル処理を起動すると遅い
引数で受け取ったファイルを逐次処理していると遅い。
ARGV.each{|f| `mogriy -resize 1000 #{f}` `mogriy -strip #{f}` }
じゃぁ連続大量起動は重い
だからといって、大量起動すると、ファイル数が100超えた時ひどく遅くなる。
ARGV.map{|f| Thread.new{ `mogriy -resize 1000 #{f}` `mogriy -strip #{f}` } }.each{|t| t.join}
じゃぁ、Queue 作って。。。
Queue使えば出来るよね。でも面倒だし、変数増えるし、処理が一貫しない。
#!/usr/bin/env ruby #!/usr/bin/env ruby require 'thread' q = Queue.new ARGV.each{|f| q.push f } p = Proc.new{|f| until q.empty? do puts q.pop sleep 1; end } threads =[] threads << Thread.new(&p) threads << Thread.new(&p) threads << Thread.new(&p) threads << Thread.new(&p) threads << Thread.new(&p) threads.each{|t| t.join }
変数増えるし、Proc出てくるし、パッと見分からないし、あんまり嬉しくないですね。
なにより、rubyのThredってeachと相性悪く、each内でthread使うとコードが読みにくくなってですね。。
関連資料
今回使ったマルチスレッドのデザパタ
Rubyマルチスレッドその1 - それマグで!
Rubyでマルチスレッド 13 #thread specific Storage - それマグで!
Rubyでマルチスレッド その5 # Guarded Suspension - それマグで!
マルチスレッド・デザイン・パターンがすごく役に立ってて嬉しい。デザパタ本オススメ
参考資料
http://doc.ruby-lang.org/ja/1.8.7/library/thread.html
http://www.ruby-doc.org/stdlib-2.0/libdoc/thread/rdoc/Queue.html
http://blog.kteru.net/archives/533
http://d.hatena.ne.jp/vividcode/20100813/1281709854
http://yakinikunotare.boo.jp/orebase/index.php?Ruby%2F%A5%D6%A5%ED%A5%C3%A5%AF%B9%BD%CA%B8