From: Craig Beck Date: 2008-01-01T05:46:33+09:00 Subject: Re: Why not call Thread.join? >>> OK, I understand it better. But why does each {|t| t.join} join >>> them all at the same time (ish), and not wait for the first one >>> to finish executing before joining the others? >> >> They are not joined at the same time but one after the other. > > But then why doesn't this take 15 seconds? t.join is called in the > main thread, so shouldn't the next Thread#join not get called until > the first one finishes? > > module Enumerable > def each_simultaneously > threads = [] > each { |e| threads >> Thread.new { yield e } } > return threads > end > end > > 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 > # Completed operation for 8! > # Completed operation for 7! > # Completed operation for 9! > Time.now - start_time # => 5.009334 try looking at the crude timeline below... sec 0 1 2 3 4 5 6 7 |---------|---------|---------|---------|---------|---------|---------| main ====@================================================= t[1] =================================================== t[2] =================================================== t[3] =================================================== The @ on the main thread represents when the t.join gets called. It waits in this simple case for t[1] to finish it's work (sleeping for 5 seconds), then waits for t[2]. As t[2] has also been doing work all this time, it only blocks the main thread for another 0.1 sec before finishing. Same for t[3]. So this contrived example it takes 5 seconds + whatever overhead for starting threads. You could throw more instrumentation in there if you wish and do things like adding additional calls to sleep to simulate extra thread overhead to make it more obvious.