2008-11-20 23 views

Respuesta

24

Puede usar el método de kernel fork. Este es un ejemplo:

#!/usr/bin/env ruby 
puts "This is the master process." 

child_pid = fork do 
    puts "This is the child process" 
    exit 
end 

puts "The PID of the child process is #{child_pid}" 

El método fork devuelve el PID del proceso se bifurca y ejecuta cualquier código en el bloque pasado. Al igual que los bloques regulares de Ruby, mantiene los enlaces del proceso principal.

Es una buena idea hacer su proceso bifurcado exit.

+1

Una cosa para recordar con Ruby es que no todas las cosas funcionan exactamente de la misma manera en Windows frente a * nix. A veces no se implementan completamente en Windows, por lo que debe usar bajo su propio riesgo. – Daemin

+7

Éste no funcionaría en Windows en absoluto – vava

+6

@Vadim Creo que es una característica, no un error. –

36

Además de la gran respuesta de Chris, recuerde llamar al Process.wait de su maestro para cosechar el proceso de su hijo, de lo contrario dejará zombies atrás.

ejemplo como se solicita en los comentarios:

pid = Process.fork do 
    puts "child, pid #{Process.pid} sleeping..." 
    sleep 5 
    puts "child exiting" 
end 

puts "parent, pid #{Process.pid}, waiting on child pid #{pid}" 
Process.wait 
puts "parent exiting" 
+0

Dulce, eso fue un consejo increíble. –

+1

¿Dónde y cómo colocaría Process.wait en la respuesta aceptada anteriormente? – iamtoc

+7

Tenga en cuenta que 'Process.wait' sin un argumento espera _any_ child, por lo que en un caso más general, este fragmento de código saldrá del elemento primario incluso si ese proceso secundario específico anterior no se cierra. Una versión más exacta diría 'Process.wait (pid)' en su lugar. – sameers

2

Si usted está dispuesto a utilizar hilos, en lugar de Procesos, entonces algo como esto puede ser un poco más escalable a más-que-un tenedor:

def doit(x) 
    sleep(rand(10)) 
    puts "Done... #{x}" 
end 

thingstodo = ["a","b","c","d","e","f","g"] 
tasklist = [] 

# Set the threads going 

thingstodo.each { |thing| 
    task = Thread.new(thing) { |this| doit(this) } 
    tasklist << task 
} 

# Wait for the threads to finish 

tasklist.each { |task| 
    task.join 
} 

Consulte los excelentes comentarios y referencias de John Topley a continuación, sobre el modelo de ejecución de Ruby y sus restricciones.


acaba de editar para corregir un error evidente (sin asignación de tareas), y para seguir a @ consejos (Jason King) 's.

+0

¿Se supone que estos son hilos verdes en lugar de los hilos adecuados del sistema operativo? –

+2

Lea esto respecto a Ruby 1.9: http://www.igvita.com/2008/11/13/concurrency-is-a-myth-in-ruby/ –

+0

Debería ser: 'Thread.new (thing) {| it | doit (it)} ' Porque' thing' se restablece en cada iteración, por lo que no hay garantía de que el hilo correcto obtenga la 'cosa correcta' – smathy

2

Una buena alternativa al tenedor/exec/desove es la joya POSIX-desove para Ruby 1.9: https://github.com/rtomayko/posix-spawn

Se hizo la mayor parte del trabajo duro para que sea más fácil, eficiente y flexible en comparación con los métodos de nivel inferior.

Cuestiones relacionadas