2

join当要加入的线程尚未完成时,调用线程将阻塞父线程。为了检查这一点,我创建了以下代码:

threads = []
3.times do |i|
  threads << Thread.new do
    3.times do |j|
      puts "Thread #{i} says #{j} (#{Thread.current})"
      sleep 0.1
    end
  end
end

#threads.map(&:join)
threads[0].join
puts "After first join"
threads[1].join
puts "After second join"
threads[2].join
puts "Last line of main thread"

运行这样的代码会给出以下输出:

Thread 0 says 0 (#<Thread:0x007fdceb0b8568>)
Thread 2 says 0 (#<Thread:0x007fdce982bb08>)
Thread 1 says 0 (#<Thread:0x007fdceb0b8450>)
Thread 0 says 1 (#<Thread:0x007fdceb0b8568>)
Thread 1 says 1 (#<Thread:0x007fdceb0b8450>)
Thread 2 says 1 (#<Thread:0x007fdce982bb08>)
Thread 1 says 2 (#<Thread:0x007fdceb0b8450>)
Thread 2 says 2 (#<Thread:0x007fdce982bb08>)
Thread 0 says 2 (#<Thread:0x007fdceb0b8568>)
After first join
After second join
Last line of main thread

为什么 rubyAfter first join​​ 会在线程指令之后打印,尽管该指令threads[1].join是在该打印指令之后执行的?

4

1 回答 1

3

因为之前完成的puts "Thread #{i} says #{j} (#{Thread.current})"部分(或全部)。之后执行的事实不影响结果。threads[1]puts "After first join"threads[1].joinputs "After first join"

您似乎有两点逻辑缺陷。应按如下方式对其进行更正:

  • 如果puts "Thread #{i} says #{j} (#{Thread.current})"ofthreads[1]puts "After first join"在主线程之前完成的,那么整个是否在启动threads[1]之前完成 puts "After first join"是无关紧要的。
  • threads[1]有机会 puts "After first join"在主线程执行之前完成。threads[1].join仅在其他情况下显示效果。

可能发生的事情(实际上确实发生了)是,因为threads[0].join在任何puts方法调用之前,主线程一直在休眠直到threads[0]完成。并且从threads[1]之后threads[2]立即开始threads[0],三个子线程几乎同时完成。换句话说,如果您等待足够的时间threads[0]来完成,那么其他两个线程很可能也会完成。

于 2013-07-20T13:54:10.660 回答