我的 Perl 脚本需要同时运行多个线程...
use threads ('yield', 'exit' => 'threads_only');
use threads::shared;
use strict;
use warnings;
no warnings 'threads';
use LWP::UserAgent;
use HTTP::Request;
use HTTP::Async;
use ...
...并且此类线程需要从网络获取一些信息,因此HTTP::Async
使用。
my $request = HTTP::Request->new;
$request->protocol('HTTP/1.1');
$request->method('GET');
$request->header('User-Agent' => '...');
my $async = HTTP::Async->new( slots => 100,
timeout => REQUEST_TIMEOUT,
max_request_time => REQUEST_TIMEOUT );
但是只有当其他线程这样说时,某些线程才需要访问网络。
my $start = [Time::HiRes::gettimeofday()];
my @threads = ();
foreach ... {
$thread = threads->create(
sub {
local $SIG{KILL} = sub { threads->exit };
my $url = shift;
if ($url ... ) {
# wait for "go" signal from other threads
}
my ($response, $data);
$request->url($url);
$data = '';
$async->add($request);
while ($response = $async->wait_for_next_response) {
threads->yield();
$data .= $response->as_string;
}
if ($data ... ) {
# send "go" signal to waiting threads
}
}
}, $_);
if (defined $thread) {
$thread->detach;
push (@threads, $thread);
}
}
可能有一个或多个线程在等待“go”信号,并且可能有一个或多个线程可以发送这样的“go”信号。信号量一开始的状态是“ wait ”,一旦变成“ go ”,就一直这样。
最后,应用程序检查最大运行时间。如果线程运行时间过长,则会发送自终止信号。
my $running;
do {
$running = 0;
foreach my $thread (@threads) {
$running++ if $thread->is_running();
}
threads->yield();
} until (($running == 0) ||
(Time::HiRes::tv_interval($start) > MAX_RUN_TIME));
$running = 0;
foreach my $thread (@threads) {
if ($thread->is_running()) {
$thread->kill('KILL');
$running++;
}
}
threads->yield();
现在说到重点。我的问题是:
我怎样才能最有效地在脚本中编写等待“信号量”的代码(参见上面脚本中的注释)。我应该只使用带有一些虚拟
sleep
循环的共享变量吗?我是否需要
sleep
在应用程序末尾添加一些循环以给线程时间进行自毁?