How do I manage ruby threads so they finish all their work?

匿名 (未验证) 提交于 2019-12-03 02:46:02

问题:

I have a computation that can be divided into independent units and the way I'm dealing with it now is by creating a fixed number of threads and then handing off chunks of work to be done in each thread. So in pseudo code here's what it looks like

# 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 

Basically once the initial number of threads is created each one does some work and then keeps taking stuff to be done from the work stack until nothing is left. Everything works fine when I run things in irb but when I execute the script using the interpreter things don't work out so well. I'm not sure how to make the main thread wait until all the work is finished. Is there a nice way of doing this or am I stuck with executing sleep 10 until work_units.empty? in the main thread

回答1:

If you modify spawn_thread_for to save a reference to your created Thread, then you can call Thread#join on the thread to wait for completion:

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... 

produces:

abxyzc 

(Stolen from the ri Thread.new documentation. See the ri Thread.join documentation for some more details.)

So, if you amend spawn_thread_for to save the Thread references, you can join on them all:

(Untested, but ought to give the flavor)

# 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) 


回答2:

In ruby 1.9 (and 2.0), you can use ThreadsWait from the stdlib for this purpose:

require 'thread' require 'thwait'  threads = [] threads << Thread.new { } threads << Thread.new { } ThreadsWait.all_waits(*threads) 


回答3:

It seems like you are replicating what the Parallel Each (Peach) library provides.



回答4:

Thread.list.each{ |t| t.join unless t == Thread.current } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!