Rubyでスレッド使うときの雛形みたいなやつ
スレッド間の変数の扱いとかスレッド管理とかチェックしたついでに。
重たい処理を何度も実行する必要があって、並列に処理したい場合を想定。
スレッドが終了しないうちに新しい処理が来て間に合わない。のでスレッドオブジェクトを配列に貯めておいて、順番に並列に処理するようにする。
1つのスレッドが終わるまでの時間と、配列に溜まっていくスレッドオブジェクト達とのバランス調整が必要。
Producer-Consumerパターンとか言うらしい。
使うときはこっち。Rubyでスレッドを簡単に扱うための何か - juntkの日記
# encoding: utf-8 # ruby -v => 1.8.7 require "thread" class ThreadTest def initialize() # スレッド管理用 @t = [] # スレッドの並列度(同時実行数) @threadConcurrency = 2 end def addThread(aObject = nil) # スレッド管理用の配列にスレッド入れる @t << Thread.new do # Thread#wakeupでスレッドを開始したいので、スレッドを止めとく # Thread#stopするとThread#statusは"sleep"になる Thread.stop # なんか重い処理 worker(aObject) end end def controlThread() # スレッドの並列実行数の調整と終了したスレッドの破棄 begin # 実行中のスレッド数のチェック用 runThreadNum = 0 # 停止中のスレッドリスト stopThreadList = [] @t.each_with_index do |v,i| # 終了したスレッドをスレッド管理用配列から破棄 # Thread#statusがfalseのときスレッドが正常終了してる if v.status == false or v.status == "abort" or v.status == nil then @t.delete_at(i) elsif v.status == "run" then runThreadNum += 1 elsif v.status == "sleep" then # Thread#stop?は終了(dead)または停止(stop)のときにtrueを返す # -> これ、スレッドで行う処理の中にsleep 10とかあるとtrueが返ってきます。 stopThreadList << v else end end # 実行中のスレッド数と停止中のスレッドが分かったので # 並列実行度を元に停止状態(stop)のスレッドを実行可能状態(run)にする。 (@threadConcurrency - runThreadNum).times do |t| # 雑というか無駄すぎる^^; if stopThreadList.size > 0 then stopThreadList.shift.run end end rescue error p error end end def loop() # ゲームとかグラフィック描画とかのループメソッドを想定 begin # canvasDrawとか # 座標情報とか? point = [10,10] # addThreadの引数はThreadとは関係なし # Workerで使うデータとか渡すといいよね addThread(point) # スレッドの管理 controlThread() puts "loop" p @t sleep 1 end while true end def worker(aObject=nil) # スレッドで行う処理 # 注意!このメソッド中ではsleep nが使えません。 # 使うとThreadが落ちます。例外も出ないよ # テキトーに重い処理 1000000.times do |t| a = Math.sqrt(Math.sqrt(t) * Math.sqrt(t)) end end end ThreadTest.new().loop()
QueueとSizedQueueとThread.listとThread#joinを使えばもっと簡単に書けた、というオチ。
Rubyでマルチスレッドプログラミング