独立したユニットに分割できる計算があり、これを処理する方法は、固定数のスレッドを作成し、各スレッドで実行される作業のチャンクを渡すことです。だから擬似コードでここにそれがどのように見えるかです
# main thread
work_units.take(10).each {|work_unit| spawn_thread_for work_unit}
def spawn_thread_for(work)
Thread.new do
do_some work
more_work = work_units.pop
spawn_thread_for more_work unless more_work.nil?
end
end
基本的に、最初の数のスレッドが作成されると、各スレッドはいくつかの作業を行い、何もなくなるまで作業スタックから実行するものを取り出し続けます。 irbで物事を実行するとすべてが正常に動作しますが、インタープリターを使用してスクリプトを実行すると、物事はあまりうまくいきません。すべての作業が完了するまでメインスレッドを待機させる方法がわかりません。これを行う良い方法はありますか、それともsleep 10 until work_units.empty?
メインスレッド
作成したThread
への参照を保存するようにspawn_thread_for
を変更する場合、完了を待機するスレッドでThread#join
を呼び出すことができます。
x = Thread.new { sleep 0.1; print "x"; print "y"; print "z" }
a = Thread.new { print "a"; print "b"; sleep 0.2; print "c" }
x.join # Let the threads finish before
a.join # main thread exits...
生成する:
abxyzc
(ri Thread.new
のドキュメントから盗まれました。詳細については、ri Thread.join
のドキュメントを参照してください。)
したがって、spawn_thread_for
を修正してスレッド参照を保存すると、それらすべてに結合できます。
(未テストですが、味を与える必要があります)
# main thread
work_units = Queue.new # and fill the queue...
threads = []
10.downto(1) do
threads << Thread.new do
loop do
w = work_units.pop
Thread::exit() if w.nil?
do_some_work(w)
end
end
end
# main thread continues while work threads devour work
threads.each(&:join)
Ruby 1.9(および2.0)では、この目的でstdlibのThreadsWait
を使用できます。
require 'thread'
require 'thwait'
threads = []
threads << Thread.new { }
threads << Thread.new { }
ThreadsWait.all_waits(*threads)
Parallel Each( Peach )ライブラリが提供するものを複製しているようです。
Thread.list.each{ |t| t.join unless t == Thread.current }
Thread#join を使用できます
join(p1 = v1)public
呼び出しスレッドは実行を一時停止し、thrを実行します。 thrが終了するか、limit秒が経過するまで戻りません。制限時間が切れるとnilが返され、そうでなければthrが返されます。
Enumerable#each_slice を使用して、作業単位をバッチで反復することもできます
work_units.each_slice(10) do |batch|
# handle each work unit in a thread
threads = batch.map do |work_unit|
spawn_thread_for work_unit
end
# wait until current batch work units finish before handling the next batch
threads.each(&:join)
end