使用Perl进行线程处理,如何同时执行我的线程

时间:2017-06-09 03:32:51

标签: perl

我需要同时执行~500个线程,以下是我当前开发的代码。我遇到的问题是我的线程一个接一个地执行(不是异步)。

下面的代码基本上贯穿一个符号循环,告诉我们要执行什么类型的线程,但我需要它们同时启动。

no warnings;
while ( my $row =
       shift( @{$rowcache} )
    || shift( @{ $rowcache = $sth->fetchall_arrayref( undef, $max_rows ) } ) )
{    
    my $prod_filter = "perl /home/zad0xlik/qtrack/1.2.v.chain_pg_sputnik.pl @{$row} " . lc(substr(join('', @{$row}), 0, 1)) . "_optsputnik";

    @running = threads->list(threads::running);
    print "LOOP $i\n";
    print "  - BEGIN LOOP >> NB running threads = "
      . ( scalar @running ) . "\n";

    if ( scalar @running < $nb_process ) {

        my $thread = threads->new( sub { system( ${prod_filter} ); } );

        #my $thread = threads->new( sub { sleeping_sub($i, \@a, \@b) });
        push( @Threads, $thread );
        my $tid = $thread->tid;
        print "  - starting thread $tid\n";
    }
    @running = threads->list(threads::running);
    print "  - AFTER STARTING >> NB running Threads = "
      . ( scalar @running ) . "\n";
    foreach my $thr (@Threads) {
        if ( $thr->is_running() ) {
            my $tid = $thr->tid;
            print "  - Thread $tid running\n";
        }
        elsif ( $thr->is_joinable() ) {
            my $tid = $thr->tid;
            $thr->join;
            print "  - Results for thread $tid:\n";
            print "  - Thread $tid has been joined\n";
        }
    }

    @running = threads->list(threads::running);
    print "  - END LOOP >> NB Threads = " . ( scalar @running ) . "\n";
    $i++;

}

print "\nJOINING pending threads\n";
while ( scalar @running != 0 ) {
    foreach my $thr (@Threads) {
        $thr->join if ( $thr->is_joinable() );
    }
    @running = threads->list(threads::running);
}

1 个答案:

答案 0 :(得分:0)

行。你真的误解了线程在perl中的工作方式。它们不轻巧。你不应该使用500个。

...即使你这样做,线程调用system来运行另一个perl脚本也是一个糟糕的解决方案。并发500个并发需要500个处理器才能同时运行。所以无论如何他们都会排队。

如果你真的想要进行线程化,我建议使用worker threads model,每个核心产生2个线程,并为它们排队。

至于所有从“同一时间”开始的 - 这里的答案是首先实例化你的线程,并使用semaphore开始它们。

但我真的建议你提出另一个问题,概述你要完成的任务(并提供目前为止的代码),因为我很确定会有比500线程更好的方法。

特别是 - 我想你只想打开一个exec文件句柄,并使用IO::Select从子进程中读取。

E.g:

while ( stuff ) { #e.g. your query
  open ( my $data, '-|,' $prod_filter ); 
  push @all_filehandles, $data;  
}
my $select = IO::Select -> new ( @all_filehandles ); 

while ( my @readable = $select -> can_read ) {
    foreach my $fh ( @readable ) { 
       my $line = <$fh>;
       print $line;
    }
}

无论如何都是这样的。