To me the important point in addition to the parallelism is that, when
run in batch mode, say with SciTE, main takes less than a second and
kills all the threads. Hence the messages are never seen. To see
the reports you have to do something like
start_time = Time.now
[7,8,9].each_simultaneously do |e|
sleep(5) # Simulate a long, high-latency operation
print "Completed operation for #{e}!\n"
end
sleep 5 #######main must take at least 5 seconds!!!!
Sorry to say that, but this is a bogus solution. Using sleep for this is not a good idea: if tasks take longer then you will loose output anyway or even risk that some tasks are not finished properly, if all tasks are finished much faster you'll waste time.
The thread killing is the exact reason why #each_simultaneously was built to return an Array of Thread objects. That way you can join all the threads.
# Completed operation for 8!
# Completed operation for 7!
# Completed operation for 9!
Time.now - start_time # => 5.009334
to guarantee that the threads have 5 seconds to finish
their operation. Or you can use
module Enumerable
def each_simultaneously
collect {|e| Thread.new {yield e}}.each {|t| t.join}
end
end
which guarantees that the threads will finish before
control is returned to main.
I prefer the solution that does not join in the method but returns Threads. If you think about it, that version is significantly more flexible. You can join those threads immediately
an_enum.each_simultaneously {|e| ... }.each {|th| th.join}
but you can as well do some work in between
threads = an_enum.each_simultaneously {|e| ... }
do_some_work
...
threads.each {|th| th.join}
I realize that much of this may have been obvious to some
who replied, but as a newby it wasn't to me until I read
the section and played with the code.
When I was initially confronted with multithreading it also took me a while. For me at the time it was difficult to not confuse Thread objects with threads. This was in Java which decouples Thread object creation and thread execution, which probably makes it a bit easier to grasp the concepts.
It is important to keep this distinction in mind: a Thread object in a way is an object that is like any other object just with the added twist that it *may* be associated with an independent thread of execution (i.e. in Java it is not associated until the thread starts and after the thread terminates, in Ruby the association is there right from the start because threads are started immediately and lasts until the thread terminates).
Kind regards
robert
···
On 01.01.2008 03:25, Ian Whitlock wrote: