多线程 – perl线程自我分离
我对perl(以及编程也是)很新,并且在过去的几周内一直在玩线程,到目前为止,我明白使用它们执行一些类似的并行任务是令人沮丧的 – 如果你的线程数量,内存消耗是无法控制的取决于一些输入值,并简单地限制该数字和做一些临时连接似乎非常愚蠢.
所以我试图欺骗线程通过队列返回一些值,然后分离这些线程(并没有实际加入它们) – 这是一个并行ping的例子: #!/usr/bin/perl # use strict; use warnings; use threads; use NetAddr::IP; use Net::Ping; use Thread::Queue; use Thread::Semaphore; ########## get my IPs from CIDR-notation ############# my @ips; for my $cidr (@ARGV) { my $n = NetAddr::IP->new($cidr); foreach ( @{ $n->hostenumref } ) { push @ips,( split( '/',$_ ) )[0]; } } my $ping = Net::Ping->new("icmp"); my $pq = Thread::Queue->new( @ips,undef ); # ping-worker-queue my $rq = Thread::Queue->new(); # response queue my $semaphore = Thread::Semaphore->new(100); # I hoped this may be usefull to limit # of concurrent threads while ( my $phost = $pq->dequeue() ) { $semaphore->down(); threads->create( { 'stack_size' => 32 * 4096 },&;ping_th,$phost ); } sub ping_th { $rq->enqueue( $_[0] ) if $ping->ping( $_[0],1 ); $semaphore->up(); threads->detach(); } $rq->enqueue(undef); while ( my $alive_ip = $rq->dequeue() ) { print $alive_ip,"n"; } 我找不到一个关于thread-> detach()应该如何在一个线程子程序中工作的全面描述,并认为这可能有用……而且它确实 – 如果我在主程序(线程)中做了一些事情延长它的生命周期(睡眠做得很好),所以所有分离的线程完成并将它们的部分排入我的$rq,否则它将运行一些线程将其结果收集到队列并退出警告,如: Perl exited with active threads: 5 running and unjoined 0 finished and unjoined 0 running and detached 使主程序暂时“休眠”一段时间,再一次看起来很愚蠢 – 有没有办法让线程完成他们的东西并且只能在实际的thread-> detach()调用之后分离? 解决方法
分离一个帖子并不是特别有用,因为你有效地说“他们退出时我不在乎”.
这通常不是您想要的 – 您的流程在线程仍在运行时完成. 通常情况下 – 创建线程会产生开销,因为您的进程被克隆在内存中.你想避免这样做. Thread :: Queue也很好用,因为它是一种传递信息的线程安全方式.在你的代码中,你实际上并不需要$pq,因为你实际上并没有在你使用它的时候进行线程化. 你的信号量是这样做的一种方法,但我可以建议作为替代: #!/usr/bin/perl use strict; use warnings; use Thread::Queue; my $nthreads = 100; my $ping_q = Thread::Queue -> new(); my $result_q = Thread::Queue -> new(); sub ping_host { my $pinger = Net::Ping->new("icmp"); while ( my $hostname = $ping_q -> dequeue() ) { if ( $pinger -> ping ( $hostname,1 ) ) { $result_q -> enqueue ( $hostname ); } } } #start the threads for ( 1..$nthreads ) { threads -> create ( &;ping_host ); } #queue the workload $ping_q -> enqueue ( @ip_list ); #close the queue,so '$ping_q -> dequeue' returns undef,breaking the while loop. $ping_q -> end(); #wait for pingers to finish. foreach my $thr ( threads -> list() ) { $thr -> join(); } $results_q -> end(); #collate results while ( my $successful_host = $results_q -> dequeue_nb() ) { print $successful_host,"n"; } 这样,您可以预先生成线程,对目标进行排队,然后在完成后整理结果.您不会产生重复重新生成线程的开销,并且您的程序将等待所有线程完成.这可能有一段时间了,因为’down’主机上的ping超时将会持续一段时间. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |