用线程打开的perl队列文件

时间:2013-01-10 15:30:50

标签: multithreading perl

我有多线程的简单站点检查器。 我在这个目录中尝试打开循环txt文件

my @files = glob( '*.txt' );

foreach my $file(@files){

   @sites=load_file($file);
   $total_count = scalar(@sites);

   for my $t (1..$threads) {
     push @threads, threads->create(\&check, $t);#check- main subroutine
     threads->create(\&stat)->join() if $t == $threads;#stat - realtime statistics(good/bads) sites
   }

   foreach my $t (@threads) {
     $t->join();
   }
}

但它仅适用于第一个文件和程序终止。 有人可以帮忙吗? 感谢。

2 个答案:

答案 0 :(得分:2)

“站点检查器”当然是一个I / O绑定问题,而线程/分叉更适合解决CPU绑定问题。如果使用异步方法,则通过网络的并行请求可以是单进程的。这是一个使用CPAN YADA模块的非常简单的检查器,它默认使用4个并行连接:

#!/usr/bin/env perl
use common::sense;

use YADA;

YADA->new->append(
    [qw[
        http://www.cpan.org/modules/by-category/02_Language_Extensions/
        http://www.cpan.org/modules/by-category/02_Perl_Core_Modules/
        http://www.cpan.org/modules/by-category/03_Development_Support/
        http://www.cpan.org/modules/by-category/27_Pragma/
        http://www.cpan.org/modules/by-category/28_Perl6/
        http://www.cpan.org/modules/by-category/99_Not_In_Modulelist/
    ]] => sub {
        say $_[0]->final_url;
        say ${$_[0]->header};
    },
)->wait;

答案 1 :(得分:2)

如果您正在使用Perl进行线程处理,则需要避免一些事项:

  • 过度分叉/创建新流程
  • 共享状态,或共享任何不可变或同步的内容!

您的代码使用$threads的硬连线限制。但是你传递并索引到一个全局(* shudder *)数组(忘记第一个索引),所以有些网站可能会被取消选中。此外,您为每组网站创建一组新线程,这似乎很浪费。

现在假设我们有一个Thread :: Queue。然后我们从创建几个线程开始:

#!/usr/bin/perl

use strict; use warnings; use threads; use Thread::Queue;
use constant THREADS => 5; # or whatever

my $queue = Thread::Queue->new();

my @threads = map threads->new(\&check, $queue),  1 .. THREADS;

我们的check子例程将队列作为参数,从中获取站点:

sub check {
  my $q = shift;
  while (defined(my $site = $q->dequeue)) {
    ...; # check the site.
  }
}

然后(在启动线程之后),我们用站点填充队列:

for my $file (@files) {
   my @sites = load_file($file);
   $queue->enqueue( @sites ); # keep queue operations to minimum
   # maybe wait until there are less that n sites in the queue
}

文件完成后,我们将undef值排队;这导致线程终止:

$queue->enqueue( (undef) x THREADS );
$_->join for @threads;