Thread.join阻塞主线程

时间:2021-01-05 20:44:58

Calling Thread.join blocks the current (main) thread. However not calling join results in all spawned threads to be killed when the main thread exits. How does one spawn persistent children threads in Ruby without blocking the main thread?

调用Thread.join会阻塞当前(主)线程。但是,当主线程退出时,不会调用join会导致所有生成的线程被杀死。如何在不阻塞主线程的情况下在Ruby中生成持久子线程?

Here's a typical use of join.

这是加入的典型用法。

for i in 1..100 do
  puts "Creating thread #{i}"
  t = Thread.new(i) do |j|
    sleep 1
    puts "Thread #{j} done"
  end
  t.join
end
puts "#{Thread.list.size} threads"

This gives

这给了

     Creating thread 1  
     Thread 1 done  
     Creating thread 2  
     Thread 2 done  
     ...  
     1 threads  

but I'm looking for how to get this

但我正在寻找如何得到这个

    Creating thread 1  
    Creating thread 2  
    ...  
    101 threads  
    Thread 1 done  
    Thread 2 done  
    ...  

The code gives the same output in both Ruby 1.8.7 and 1.9.2

代码在Ruby 1.8.7和1.9.2中提供相同的输出

2 个解决方案

#1


18  

You simply accumulate the threads in another container, then join them one-by-one after they've all been created:

您只需将线程累积到另一个容器中,然后在创建它们之后逐个加入它们:

my_threads = []
for i in 1..100 do
    puts "Creating thread #{i}"
    my_threads << Thread.new(i) do |j|
        sleep 1
        puts "Thread #{j} done"
    end
end
puts "#{Thread.list.size} threads"

my_threads.each do |t|
    t.join
end

You also can't bind the thread to the i variable because i gets constantly overwritten, and your output will be 100 lines of "Thread 100 done"; instead, you have to bind it to a copy of i, which I have cleverly named j.

你也无法将线程绑定到i变量,因为我不断被覆盖,你的输出将是100行“Thread 100 done”;相反,你必须将它绑定到i的副本,我巧妙地将其命名为j。

#2


6  

You need to join the threads outside of the loop.

您需要加入循环外部的线程。

for i in 1..100 do
  puts "Creating thread #{i}"
  t = Thread.new(i) do |mi|
    sleep 1
    puts "Thread #{mi} done"
  end
end

# Wait for all threads to end
Thread.list.each do |t|
  # Wait for the thread to finish if it isn't this thread (i.e. the main thread).
  t.join if t != Thread.current
 end

#1


18  

You simply accumulate the threads in another container, then join them one-by-one after they've all been created:

您只需将线程累积到另一个容器中,然后在创建它们之后逐个加入它们:

my_threads = []
for i in 1..100 do
    puts "Creating thread #{i}"
    my_threads << Thread.new(i) do |j|
        sleep 1
        puts "Thread #{j} done"
    end
end
puts "#{Thread.list.size} threads"

my_threads.each do |t|
    t.join
end

You also can't bind the thread to the i variable because i gets constantly overwritten, and your output will be 100 lines of "Thread 100 done"; instead, you have to bind it to a copy of i, which I have cleverly named j.

你也无法将线程绑定到i变量,因为我不断被覆盖,你的输出将是100行“Thread 100 done”;相反,你必须将它绑定到i的副本,我巧妙地将其命名为j。

#2


6  

You need to join the threads outside of the loop.

您需要加入循环外部的线程。

for i in 1..100 do
  puts "Creating thread #{i}"
  t = Thread.new(i) do |mi|
    sleep 1
    puts "Thread #{mi} done"
  end
end

# Wait for all threads to end
Thread.list.each do |t|
  # Wait for the thread to finish if it isn't this thread (i.e. the main thread).
  t.join if t != Thread.current
 end