I am writing an app that retrieves multiple web pages in one method
call. Threading has improved performance drastically for me, but I
need some help understanding how exactly the call to join is going to
affect my program.
%w{methodname1 methodname2 methodname3 methodname4}.each do |method|
threads << Thread.new(method) do |m|
r = eval("#{m}(string)") # each method call makes an HTTP
request
mutex.synchronize { result.merge!(r) }
end
end
threads.each { |t| t.join }
result
end
Seems like the call to join on each thread is necessary to keep the
script from getting ahead of itself, but if I exclude that line, it
doesn't seem to hurt my results and the program runs a lot faster.
Also, sometimes I get deadlocked somehow if I do use the call to join
and I'm not certain as to why. Can someone help shed some light on the
situation? Do I need to call join? Any idea why I'm deadlocking?
Thanks!
Thread#join simply says "Wait here until this thread has finished
executing".
So what you're doing is waiting for all threads to finish before execution
continues, aka blocking main thread execution. Without the #join, the values
in results will be nonderministic. Any perceived deadlocking is probably
whatever is in your eval call not timing out. You'll have to watch out
carefully for that.
Jason
···
On Mon, Nov 9, 2009 at 3:45 PM, Matt White <mattw922@gmail.com> wrote:
I am writing an app that retrieves multiple web pages in one method
call. Threading has improved performance drastically for me, but I
need some help understanding how exactly the call to join is going to
affect my program.
Here's some code:
def method(string)
result = {}
mutex = Mutex.new
threads =
%w{methodname1 methodname2 methodname3 methodname4}.each do |method|
threads << Thread.new(method) do |m|
r = eval("#{m}(string)") # each method call makes an HTTP
request
mutex.synchronize { result.merge!(r) }
end
end
threads.each { |t| t.join }
result
end
Seems like the call to join on each thread is necessary to keep the
script from getting ahead of itself, but if I exclude that line, it
doesn't seem to hurt my results and the program runs a lot faster.
Also, sometimes I get deadlocked somehow if I do use the call to join
and I'm not certain as to why. Can someone help shed some light on the
situation? Do I need to call join? Any idea why I'm deadlocking?
Thanks!
And exception handling, etc, will be ever so much clearer.
Judson
···
On Mon, Nov 9, 2009 at 1:14 PM, Jason Roelofs <jameskilton@gmail.com> wrote:
On Mon, Nov 9, 2009 at 3:45 PM, Matt White <mattw922@gmail.com> wrote:
> I am writing an app that retrieves multiple web pages in one method
> call. Threading has improved performance drastically for me, but I
> need some help understanding how exactly the call to join is going to
> affect my program.
>
> Here's some code:
>
> def method(string)
> result = {}
> mutex = Mutex.new
> threads =
>
> %w{methodname1 methodname2 methodname3 methodname4}.each do |method|
> threads << Thread.new(method) do |m|
> r = eval("#{m}(string)") # each method call makes an HTTP
> request
> mutex.synchronize { result.merge!(r) }
> end
> end
> threads.each { |t| t.join }
> result
> end
>
> Seems like the call to join on each thread is necessary to keep the
> script from getting ahead of itself, but if I exclude that line, it
> doesn't seem to hurt my results and the program runs a lot faster.
> Also, sometimes I get deadlocked somehow if I do use the call to join
> and I'm not certain as to why. Can someone help shed some light on the
> situation? Do I need to call join? Any idea why I'm deadlocking?
> Thanks!
>
>
Thread#join simply says "Wait here until this thread has finished
executing".
So what you're doing is waiting for all threads to finish before execution
continues, aka blocking main thread execution. Without the #join, the
values
in results will be nonderministic. Any perceived deadlocking is probably
whatever is in your eval call not timing out. You'll have to watch out
carefully for that.
And exception handling, etc, will be ever so much clearer.
You can as well do
def method(string)
threads = %w{
methodname1
methodname2
methodname3
methodname4
}.map do |method|
Thread.new(method) do |m|
send(m, string) # each method call makes an HTTP request
end.map {|th| th.value}
end