我创建了一个Perl脚本,我在其中创建了线程(在此期间运行的线程方面受限)并且每个线程都创建了自己的子节点,这些子节点的数量也应该有限。
在我托管脚本的地方,我不能同时为每个Perl脚本启动超过X个线程。在下面的例子中,我同时X = 3 x 7 = 21个线程。
$nb_process_first
)$nb_process_second
)问题:
#!/usr/bin/perl -s
use threads;
my @threads;
my $nb_process_first = 3;
my @running = ();
print "START" . "\n";
$current = 1;
while ( $current <= 10 ) {
@running = threads->list(threads::running);
if ( scalar @running < $nb_process_first ) {
print "Launch firstJob=" . scalar @running . "\n";
my $thread = threads->create( \&firstJob );
push( @threads, $thread );
} else {
redo;
}
$current++;
}
my @joinable = threads->list(threads::joinable);
while ( scalar @joinable != 0 ) {
foreach my $thr ( threads->list() ) {
$thr->join();
}
@joinable = threads->list(threads::joinable);
}
print "END" . "\n";
sub secondJob {
for ( $i = 0; $i <= 15; $i++ ) {
print "secondJob=" . $i . "\n";
sleep 1;
}
threads->exit();
}
sub firstJob {
my $nb_process_second = 7;
my @running = ();
$current = 1;
while ( $current <= 10 ) {
@running = threads->list(threads::running);
if ( scalar @running < $nb_process_second ) {
print "firstJob/Launch secondJob=" . scalar @running . "-" . $current . "\n";
my $secondthread = threads->create( \&secondJob );
push( @threads, $secondthread );
sleep 2;
}
$current++;
}
threads->exit();
}
答案 0 :(得分:0)
至于你的第二个问题,线程只有在完成运行后才能连接(参见this answer)。因为某些线程在第二个while
循环运行时没有完成,所以它完成后不加入它们。
您的循环应该根据活动线程数而不是可连接线程数来等待。像这样:
while (threads->list() > 0)
{
foreach my $joinable (threads->list(threads::joinable))
{
$joinable->join();
}
}
至于第一个问题,肯定有其他方法可以管理线程。但是,如果不了解您的任务,就无法说出您应该做些什么。
答案 1 :(得分:0)
Thread::Queue
是基本&#39;工作线程的便捷模型。线程代码模型。
有点像这样:
#!/usr/bin/perl
use strict;
use warnings;
use threads;
use Thread::Queue;
my $firstworkitem_q = Thread::Queue -> new();
my $secondworkitem_q = Thread::Queue -> new();
my $nthreads = 10;
sub first_worker {
while ( my $item = $firstworkitem_q -> dequeue() ) {
print "First worker picked up $item, and queues it to second worker\n";
$secondworkitem_q -> enqueue ( $item );
}
}
sub second_worker {
while ( my $item = $secondworkitem_q -> dequeue() ) {
print "Second worker got $item";
}
}
my @first_workers;
for ( 1..$nthreads ) {
my $thr = threads -> create ( \&first_worker );
push ( @first_workers, $thr );
}
for ( 1..$nthreads ) {
my $thr = threads -> create ( \&second_worker );
}
$firstworkitem_q -> enqueue ( @things_to_processs );
$firstworkitem_q -> end;
foreach my $firstworker ( @first_workers ) {
$firstworker -> join();
}
#here all the first workers have finished, so we know nothing will be queued to second work queue.
$secondworkitem_q -> end();
foreach my $thr ( threads -> list() ) {
$thr -> join();
}
你把东西塞进队列,然后迭代它进行处理。当你end
队列时,while循环得到undef
并因此终止 - 使你的线程可以连接。
您不需要按照您的方式跟踪@running
,因为threads -> list()
会这样做。更重要的是 - 你需要让@running成为共享变量并将其锁定,因为否则你在每个线程中都有不同的副本。
让firstJob
产生secondJob
我会远离它,因为它会产生各种各样的果味错误。我建议产生两类工作线程。使用$queue -> end()
触发要关闭的第一组工作人员。