2010-06-22 9 views
9

Im Folgenden wird nicht in gleichzeitigen Threads laufen, wie ich erwartet hatte, sondern jeder Prozess blockiert, bis er abgeschlossen ist:Wie gleichzeitige Threads in Perl ausgeführt werden?

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

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

Mit anderen Worten, es wird die gleiche wie die nicht-Thread-Version zu Ausführung würde:

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

I mswin32-x86-Multi-Thread ActivePerl v5.10.1

Wie ich laufen gleichzeitige Threads in perl ausführe?

Antwort

12

Siehe perldoc threads.

Das Problem ist, dass Aufruf join() auf einen Thread wartet, bis es fertig ist. Sie möchten Threads spawnen und dann danach beitreten, nicht spawn/join als eine Operation.

Ein weiterer Blick auf perldoc threads sagt:

threads-> list()

threads-> Liste (threads :: alle)

threads-> Liste (threads :: Lauf

)

threads-> Liste (threads :: joinable)

Ohne Argumente (oder mit threads :: all) und gibt im Listenkontext eine Liste aller nicht verbundenen, nicht getrennten Thread-Objekte zurück. In einem skalaren Kontext gibt eine Anzahl derselben zurück.

Mit einem echten Argumente (mit Gewinden :: Laufen), gibt eine Liste aller nicht verbundene, nicht freistehende Objekte, die Fäden noch ausgeführt werden.

Mit einem falschen Argument (threads :: joinable) wird eine Liste aller nicht verbundenen, nicht getrennten Thread-Objekte zurückgegeben, die ausgeführt wurden (d. H. Für die -> join() nicht blockiert wird).

Sie können dies in einer Schleife und Liste Threads verwenden, wenn möglich, Fügen, bis alle Threads abgeschlossen sind (und Sie werden wahrscheinlich wollen eine Obergrenze Zeit warten, wo man sie töten und Abbruch)

+0

Ich habe dies versucht - nur auf einmal spawnen, dann durch die Threads und Beitritt, aber sobald der erste Join aufgerufen wird, blockiert es. es ist fast so, als müsste ich nachgeben, bis jeder Thread fertig ist, dann mach mit, aber ich bin mir nicht ganz sicher, wie das geht. – user210757

+4

Genau. 'Join' ist eine blockierende Operation. Aber Threads, die bereits erzeugt wurden, laufen weiter, während der Hauptprozess auf 'Join' wartet, um zurückzukehren. Wenn Sie in diesem Fall alle Threads spawnen und dann beitreten, würden Sie erwarten, dass der erste Join-Aufruf etwa 5 Sekunden dauert und alle anderen Join-Aufrufe sehr kurz sind. – mob

+0

als Antwort markiert. list(), in Kombination mit is_joinable war was ich brauchte - danke – user210757

3

join (nicht nur in Perl) bewirkt, dass der aufrufende Thread auf ein anderes Thread-Ende wartet. So erzeugt Ihr Beispiel einen Thread, wartet darauf, dass er beendet wird, und erstellt dann einen anderen Thread, sodass Sie den Eindruck bekommen, dass gar keine Threads erzeugt wurden.

+0

wie würde ich das dann erreichen? – user210757

12

Sie haben sie verbinden danach, nicht während sie die Schaffung:

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

Sie haben joinnach Laichen alle Themen zu nennen:

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

Wenn Sie kümmern sich nicht von die aus dem Thread generierte Ausgabe können Sie -> detach() für den Thread verwenden.

mein @arr = (1,2,3,4); meine @ Threads; foreach (@arr) {
mein $ t = threads-> neu (\ & doSomething, $ _); $ t-> detach(); }

Nachdem ein Thread abgeschlossen ist, wird er zurückgewonnen und Sie müssen join() nicht aufrufen.

Dieses Modell ist gut zum Erstellen von Arbeitsbienen, die Sie nicht zurückmelden müssen.

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

Der obige Code funktioniert in einem kleinen Maßstab. Aber wenn Sie Dutzende von Threads oder mehr haben, beginnt Ihr Betriebssystem zum Stillstand.

Verwandte Themen