Ruby:等待使用join和ThreadsWait.all_waits完成的所有线程 - 有什么区别?

sky*_*der 5 ruby multithreading thread-safety

请考虑以下示例:

threads = []

(0..10).each do |_|
  threads << Thread.new do
    # do async staff there
    sleep Random.rand(10)
  end
end
Run Code Online (Sandbox Code Playgroud)

然后有2种方法可以在完成时等待:

  1. 使用join:

    threads.each(&:join)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用ThreadsWait:

    ThreadsWait.all_waits(threads)
    
    Run Code Online (Sandbox Code Playgroud)

这两种方式之间有什么区别吗?

我知道这个ThreadsWait课有其他有用的方法.并特别询问all_waits方法.

SHS*_*SHS 6

文件明确指出,all_waits将每个线程的执行后,执行任何传递块; join不提供这样的东西.

require "thwait"

threads = [Thread.new { 1 }, Thread.new { 2 }]

ThreadsWait.all_waits(threads) do |t|
  puts "#{t} complete."
end # will return nil

# output:
# #<Thread:0x00000002773268> complete.
# #<Thread:0x00000002772ea8> complete.
Run Code Online (Sandbox Code Playgroud)

为了实现同样的目标join,我想你必须这样做:

threads.each do |t|
  t.join
  puts "#{t} complete."
end # will return threads
Run Code Online (Sandbox Code Playgroud)

除此之外,这些all_waits方法最终调用了join_nowait通过调用join它来处理每个线程的方法.

没有任何阻止,我会想象直接使用join会更快,因为你会减少ThreadsWait导致它的所有方法.所以我试了一下:

require "thwait"
require "benchmark"

loops = 100_000
Benchmark.bm do |x|
  x.report do
    loops.times do
      threads = [Thread.new { 2 * 1000 }, Thread.new { 4 * 2000 }]
      threads.each(&:join)
    end
  end

  x.report do
    loops.times do
      threads = [Thread.new { 2 * 1000 }, Thread.new { 4 * 2000 }]
      ThreadsWait.all_waits(threads)
    end
  end
end

# results:
# user       system     total       real
# 4.030000   5.750000   9.780000  ( 5.929623 )
# 12.810000  17.060000  29.870000 ( 17.807242 )
Run Code Online (Sandbox Code Playgroud)