2009-11-08 5 views
5

tengo una tarea que necesito para llevar a cabo, do_stuff(opts), que se llevará a ~ 1 s cada uno, incluso mientras 1 - 10 de ellos están funcionando en paralelo. Necesito recopilar una variedad de resultados para cada operación al final.que rosca en Ruby con un límite

Si tengo 30 cosas para hacer, ¿cómo usaría el enhebrado de manera efectiva para poner en cola las operaciones do_stuff(opts), así que no más de 10 se ejecutan simultáneamente, pero la matriz de resultados no se da/imprime/etc. hasta que todos (30) las tareas se han completado?

por lo general tienen al menos algo de código para tratar de ilustrar lo que quiero decir, pero con el roscado estoy en un poco de una pérdida! Gracias de antemano

Respuesta

0

También, echar un vistazo a this tutorial si usted es nuevo en las discusiones de Ruby.

+1

Parece que el enlace está muerto. Hay una copia en alguna parte? – Naremy

+0

@Naremy, he arreglado el enlace. Por favor, vota cuando tienes un momento. – jkndrkn

+0

Yo no era el que menospreciaba, pero si puedo hacerlo feliz;) – Naremy

1

Si usted es realmente después de la actuación, también puede ser que desee ver en jruby.
Utiliza hebras de SO reales y no los hilos verdes las otras implementaciones rubí utilizan

4

no sé lo bien que va a trabajar para una aplicación más compleja, pero he encontrado algo como esto para trabajar muy bien para un escenario simple roscado con macruby.

thread_limit = 4 

threads = [] 
things_to_process.each do |thing| 
    until threads.map { |t| t.status }.count("run") < thread_limit do sleep 5 end 
    threads << Thread.new { the_task(thing) } 
end 
output = threads.map { |t| t.value } 

el bucle de espera hasta alrededor hasta que hay menos de la cantidad especificada de hilos creados en ejecución antes de permitir la ejecución del hilo principal para continuar en para iniciar el siguiente hilo.

a la variable de salida se le asignará una matriz de los valores devueltos por la_tarea con un orden correspondiente a la matriz de entrada things_to_process. El hilo principal se bloqueará hasta que cada hilo creado devuelva un valor.

+1

¿Mejor suerte que con thread.alive? en lugar de estado: 'threads.map {| t | t.alive?}. count (verdadero) ' – theglauber

1

Esta solución reúne los resultados en $ results array. Permite la creación de subprocesos 'thread_limit', luego espera a que se completen antes de crear más.

$results = [] 

    def do_stuff(opts={}) 
    'done' 
    end 

    def thread_wait(threads) 
    threads.each{|t| t.join} 
    threads.each {|t| $results << t } 
    threads.delete_if {|t| t.status == false} 
    threads.delete_if {|t| t.status.nil? } 
    end 

    opts = {} 
    thread_limit = 20 
    threads = [] 
    records.each do |r| 
    thread_wait(threads) while threads.length >= thread_limit 
    t = Thread.new { do_stuff(opts) } 
    t.abort_on_exception = true 
    threads << t 
    end 
    # Ensure remaining threads complete 
    threads.each{|t| t.join} 
0

utilizo parals y paralsmap:

def parals(objects, n: 50) 
    objects.shuffle.each_slice(n).map do |g| 
    print '{' 
    threads = [] 
    g.map { |i| threads << Thread.new(i) { |i| yield(i) } } 
    threads.each(&:join) 
    print '}' 
    end 
end 

def paralsmap(objects, n: 50) 
    res = [] 

    objects.each_slice(n).map do |g| 
    print '{' 
    threads = [] 
    g.map { |i| threads << Thread.new(i, res) { |i| res << yield(i) } } 
    threads.each(&:join) 
    print '}' 
    end 

    res 
end 

ej .:

parals((0..100).to_a) { |i| puts i } 
urls = parals((0..100).to_a) { |i| "https://google.com/?q=#{i}" } 

Puede utilizar el parámetro n para limitar el número de hilos.

Cuestiones relacionadas