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

この印刷命令の後に命令が実行されたにもかかわらず、なぜルビはAfter first joinスレッドの命令の後に印刷したのですか?threads[1].join

4

1 に答える 1

3

puts "Thread #{i} says #{j} (#{Thread.current})"一部 (またはすべて) が のthreads[1]前に終了したためputs "After first join"です。threads[1].join後に実行された事実puts "After first join"は結果に影響しません。

あなたには論理的な欠陥が 2 点あるようです。次のように修正する必要があります。

  • メインスレッドの前に実行された場合puts "Thread #{i} says #{j} (#{Thread.current})"、開始前に全体が実行された かどうかは関係ありません。threads[1]puts "After first join"threads[1]puts "After first join"
  • threads[1]puts "After first join"メインスレッドが実行される前に実行される可能性があります 。threads[1].joinそれ以外の場合にのみ効果を示します。

そして、起こりそうなこと (実際に起こったこと) は、メソッド呼び出しのthreads[0].joinputsに、メイン スレッドが終了するまでスリープしていたことthreads[0]です。そして、 と の直後に開始されて以来threads[1]threads[2]3threads[0]つのサブスレッドはほぼ同時に終了しました。つまり、 が終了するまで十分な時間待機するthreads[0]と、他の 2 つのスレッドも終了する可能性が高くなります。

于 2013-07-20T13:54:10.660 に答える