Thread.joinのイディオム

いままでよく使ってたイディオム

Threadを集めるArrayを用意する。

th = []
n.times do |i|
  th[i] = Thread.start{ do_something }
end
th.each(&:join)

'14/6/30追記:Arrayにpushする

th = []
n.times do
  th << Thread.new { do_something }
end
th.each(&:join)

最初の例と同じなのだけど、変数iを使わなくて済むので楽ですね。

ちょっと楽なイディオム

次の本のp.396に記載があったイディオム。

Ruby Way 第2版 (Professional Ruby Series)

Ruby Way 第2版 (Professional Ruby Series)

(なお、この本はいろいろな小技が山のように載ってるので、あると非常に便利。オススメ。)

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

つまり「メインスレッド以外のスレッドを集めて、全てjoinせよ」ということ。
一つ目のように、Thread.startを集めるArrayを用意しなくても良いので楽になる。
ただし、複数箇所でスレッドを使ってたら、変な集め方をしてしまうかもしれないけど。

使用例

#!/usr/bin/env ruby
# coding: utf-8
require 'pp'

def thread_with_array
  th = []
  10.times do |_i|
    th[_i] = Thread.start(_i) do |i|
      sleep rand(10)
      puts i
    end
  end
  th_status = th.each{ |thread| thread.join }
  pp th_status
  puts "size: #{th_status.size}"
end

def thread_without_array
  10.times do |_i|
    Thread.start(_i) do |i|
      sleep rand(10)
      puts i
    end
  end
  th_status = Thread.list.each{ |t| t.join unless t == Thread.main}
  pp th_status
  puts "size: #{th_status.size}"
end

puts "thread with array"
thread_with_array
puts "thread without array"
thread_without_array

結果:

thread with array
5
7
8
9
6
0
21

4
3
[#<Thread:0x007ff6f3019388 dead>,
 #<Thread:0x007ff6f3019248 dead>,
 #<Thread:0x007ff6f3019068 dead>,
 #<Thread:0x007ff6f3018fc8 dead>,
 #<Thread:0x007ff6f20e16b8 dead>,
 #<Thread:0x007ff6f20e1c08 dead>,
 #<Thread:0x007ff6f20e2130 dead>,
 #<Thread:0x007ff6f20e26a8 dead>,
 #<Thread:0x007ff6f20e5510 dead>,
 #<Thread:0x007ff6f20d9328 dead>]
size: 10
thread without array
6
5
8
4
7
0
1
9
23

[#<Thread:0x007ff6f20677a0 run>,
 #<Thread:0x007ff6f201d218 dead>,
 #<Thread:0x007ff6f201d128 dead>,
 #<Thread:0x007ff6f201d088 dead>,
 #<Thread:0x007ff6f201cfc0 dead>,
 #<Thread:0x007ff6f201cf20 dead>,
 #<Thread:0x007ff6f201ce80 dead>,
 #<Thread:0x007ff6f201cdb8 dead>,
 #<Thread:0x007ff6f201cd18 dead>,
 #<Thread:0x007ff6f201cc78 dead>,
 #<Thread:0x007ff6f201cbd8 dead>]
size: 11