2010-08-14 12 views
16

La llamada a Thread.join bloquea la hebra actual (principal). Sin embargo, los resultados de la combinación de llamadas en todos los subprocesos generados no se eliminarán cuando el hilo principal salga. ¿Cómo se generan hilos de niños persistentes en Ruby sin bloquear el hilo principal?Thread.join bloquea la hebra principal

Aquí hay un uso típico de 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" 

Esto da

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

pero estoy buscando la manera de conseguir este

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

El código da la misma salida, tanto en Rubí 1.8.7 y 1.9.2

Respuesta

18

Simplemente se acumulan los hilos en otro recipiente, entonces join ellos uno por uno después de que todos han sido creados:

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 

También puede se une el hilo a la i variable porque i se sobrescribe constantemente, y su salida será de 100 líneas de "Hilo 100 hecho"; en su lugar, debe vincularlo a una copia de i, que ingeniosamente he llamado j.

+0

Sí, eso funciona. Hubiera pensado que Ruby tendría una forma de manejar esto implícitamente en lugar de tener que hacer un seguimiento de los hilos y realizar una llamada de unión al final. Y sí, no debería usar el global i dentro de cada hilo. Cosas básicas. Gracias por la corrección. Actualizaré el código. – Alkaline

+5

En Ruby 1.9, los parámetros de bloque son siempre locales, por lo que no necesitaría cambiar el nombre de la variable. Aunque recibirías una advertencia. (* Variable 'i' sombras variable externa * o algo así.) –

6

Debe unir los hilos fuera del ciclo.

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 
Cuestiones relacionadas