2010-06-22 11 views
9

El siguiente no parece funcionar en hilos concurrentes como esperaba, sino que cada bloques de proceso hasta que es completa:¿Cómo ejecutar hilos concurrentes en perl?

my @arr = (1,2,3,4); 
foreach (@arr) { 
    threads->new(\&doSomething, $_)->join; 
} 

sub doSomething { 
    my $thread = shift; 
    print "thread $thread\n"; 
    sleep(5); 
} 

En otras palabras, parece ser la ejecución de la misma que la versión no roscada haría:

my @arr = (1,2,3,4); 
foreach (@arr) { 
    doSomething($_); 
} 

estoy corriendo ActivePerl v5.10.1 mswin32-x86-multi-hilo

Cómo corro hilos concurrentes en perl?

Respuesta

12

Ver perldoc threads.

El problema es que al llamar a join() en un hilo espera a que termine. Desea engendrar hilos y luego unirse después, no engendrar/unirse como una sola operación.

Una mirada más a fondo en perldoc threads dice:

threads-> lista()

threads-> lista (hilos) :: todas

threads-> lista (hilos de ejecución ::)

threads-> lista (hilos) que se pueden unir ::

Sin argumentos (o usando threads :: all) y en un contexto de lista, devuelve una lista de todos los objetos de subprocesos no unidos no unidos. En un contexto escalar, devuelve un conteo del mismo.

Con un verdadero argumento (utilizando hilos :: funcionamiento) , devuelve una lista de todos, hilos no unifamiliar objetos no afiliados que se aún en marcha.

Con un argumento falso (usando threads :: joinable), devuelve una lista de todos los objetos de hilos no unidos, no separados que han terminado de ejecutarse (es decir, para los que -> join() no se bloqueará).

Usted puede usar esto para hilos de bucle y de la lista, uniéndose cuando sea posible, hasta que todos los hilos están completas (y probablemente querrá un límite superior para el tiempo de espera donde se matarlos y abortar)

+0

He intentado esto - simplemente generando de inmediato, luego iterando a través de los hilos y uniéndolos, pero tan pronto como se llama a la primera unión, bloquea. es casi como si tuviera que ceder hasta que cada hilo esté completo, luego unirse, pero no estoy muy seguro de cómo hacerlo – user210757

+4

Exactamente. 'join' es una operación de bloqueo. Pero los hilos que ya se han generado continuarán ejecutándose mientras el proceso principal está esperando que 'join 'regrese. En este caso, si genera todos los hilos y luego se une, esperaría que la primera llamada de unión tardara aproximadamente 5 segundos, y todas las demás llamadas de unión serían muy cortas. – mob

+0

marcado como respuesta. list(), en combinación con is_joinable era lo que necesitaba - gracias – user210757

3

join (no solo en Perl) provoca que el subproceso de llamada espere a que finalice otro subproceso. Por lo tanto, su ejemplo engendra el hilo, espera que termine y luego genera otro hilo, por lo que se da la impresión de que no hay ningún hilo engendrado.

+0

¿cómo iba a lograr esto entonces? – user210757

12

usted tiene que unirse a ellos después, no mientras la creación de ellos:

my @arr = (1,2,3,4); 
my @threads; 
foreach (@arr) { 
    push @threads, threads->new(\&doSomething, $_); 
} 
foreach (@threads) { 
    $_->join(); 
} 
1

Tienes que llamar joindespués desove todas las discusiones:

perl -mthreads -le'$_->join for map threads->new(sub{print"Thread $_";sleep(2)}),1..4' 
3

Si usted no cuida de la salida generada desde el hilo, puede usar -> detach() en el hilo.

my @arr = (1,2,3,4); my @threads; foreach (@arr) {
my $ t = hilos-> nuevo (\ & doSomething, $ _); $ t-> detach(); }

después de completar un hilo, se recupera y no necesita llamar a join() en él.

este modelo es bueno para crear abejas trabajadoras que no necesita informarle.

0
my @arr = (1,2,3,4); 
my @threads; 
foreach (@arr) { 
    push @threads, threads->new(\&doSomething, $_); 
} 
foreach (@threads) { 
    $_->join(); 
} 

El código anterior funciona a pequeña escala. Pero si tiene decenas de hilos o más, su sistema operativo comienza a estancarse.

Cuestiones relacionadas