Как запустить параллельные потоки в Perl? - PullRequest
9 голосов
/ 22 июня 2010

Кажется, что следующее не выполняется в параллельных потоках, как я ожидал, но каждый процесс блокируется до его завершения:

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

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

Другими словами, похоже, что он выполняется так же, как и в непоточной версии:

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

Я использую ActivePerl v5.10.1 mswin32-x86-multi-thread

Как запустить параллельные потоки в Perl?

Ответы [ 6 ]

13 голосов
/ 22 июня 2010

вы должны присоединиться к ним впоследствии , а не при их создании:

my @arr = (1,2,3,4);
my @threads;
foreach (@arr) {
   push @threads, threads->new(\&doSomething, $_);
}
foreach (@threads) {
   $_->join();
}
13 голосов
/ 22 июня 2010

См. perldoc threads.

Проблема заключается в том, что вызов join() в потоке ожидает его завершения.Вы хотите порождать потоки и затем присоединяться после, а не порождать / объединять как одну операцию.

Дальнейший взгляд на perldoc threads говорит:

threads-> list ()

threads-> list (threads :: all)

threads-> list (threads :: running)

threads-> список (threads :: joinable)

Без аргументов (или с использованием threads :: all) и в контексте списка возвращает список всех несвязанных, неотделенных объектов потоков.В скалярном контексте возвращает количество одинаковых.

С истинным аргументом (используя threads :: running) возвращает список всех не связанных, неотсоединенных объектов потоков, которые все еще работают.

С ложным аргументом (используя threads :: joinable) возвращает список всех не связанных, неотделенных потоковых объектов, которые завершили работу (т. Е. Для которых -> join () будетне блокировать).

Вы можете использовать это, чтобы зацикливать и перечислять потоки, объединяя, когда это возможно, до тех пор, пока все потоки не будут завершены (и вы, вероятно, захотите установить верхний предел времени ожидания, когда выубьет их и прервет)

3 голосов
/ 06 января 2011

Если вам не нужны выходные данные, созданные в потоке, вы можете использовать -> detach () в потоке.

my @arr = (1,2,3,4);мои @ темы;foreach (@arr) {
my $ t = threads-> new (\ & doSomething, $ _);$ T-> отсоединять ();}

после завершения потока он восстанавливается, и вам не нужно вызывать join () для него.

эта модель хороша для создания рабочих пчел, о которых вам не нужно сообщатьтебе.

3 голосов
/ 22 июня 2010

join (не только в Perl) заставляет вызывающий поток ожидать завершения другого потока.Итак, ваш пример порождает поток, ждет его завершения, а затем порождает другой поток, так что у вас создается впечатление, что потоков вообще нет

1 голос
/ 23 июня 2010

Вы должны позвонить join после , породив все темы:

perl -mthreads -le'$_->join for map threads->new(sub{print"Thread $_";sleep(2)}),1..4'
0 голосов
/ 31 января 2014
my @arr = (1,2,3,4);
my @threads;
foreach (@arr) {
   push @threads, threads->new(\&doSomething, $_);
}
foreach (@threads) {
   $_->join();
}

Приведенный выше код работает в небольшом масштабе. Но если у вас десятки потоков или больше, ваша ОС начинает зависать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...