我有多线程的简单站点检查器。 我在这个目录中尝试打开循环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();
}
}
但它仅适用于第一个文件和程序终止。 有人可以帮忙吗? 感谢。
答案 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;