Multithreading 如何限制perl中并行线程的最大数量

Multithreading 如何限制perl中并行线程的最大数量,multithreading,perl,Multithreading,Perl,我有一个程序(Perl),可以启动大量线程(每个线程负责基于数据处理创建图形)。 我开始使用的每个线程: my @threads //list to store threads that have been launched push @threads,threads->create(\mySubName,params...); 线程正常启动,但过了一段时间,在我打开其中几个线程后,Perl解释器崩溃(我认为它与内存有关?)。所以我的解决方案是限制每次打开的线程数,我选择了15个。我想

我有一个程序(Perl),可以启动大量线程(每个线程负责基于数据处理创建图形)。 我开始使用的每个线程:

my @threads //list to store threads that have been launched

push @threads,threads->create(\mySubName,params...);
线程正常启动,但过了一段时间,在我打开其中几个线程后,Perl解释器崩溃(我认为它与内存有关?)。所以我的解决方案是限制每次打开的线程数,我选择了15个。我想在每个创建行之前添加一个子线程,以检查是否可以启动下一个线程或在等待一个线程完成时执行睡眠。我就是这样做的

sub checkThreads{
    my $addThread = 0;
    until($addThread){
        my $totalThreads = 0;
        foreach my $task (@threads){
            if($task->is_running()){$totalThreads++;}
        }
        if($totalThreads <= 15 ){
            print "Ok to add new thread, carry on!\n";
            $addthread = 1;
        }else{
            print "Waiting for $totalThreads threads to fire next one...\n";
            sleep 2;
        }
    }
}
在我等待一些线程清理时,这会造成延迟。 问题是,当我呼叫该潜艇时,当我到达检查线时:

$task->is_running()
程序退出并停止运行,没有任何错误或警告。我只想要一个统计运行线程数的子线程来限制它们

如何成功执行此计数

我尝试过的其他方法是评估以下行:

scalar(threads->list());
但这给了我一个奇怪的值,好像它是一个未删减的引用,我相信它看起来像:

threads=SCALAR(0x80fea8c)
换句话说,找出threads->list()返回的列表中有多少项,然后计算出您的计数

您可能需要调查或其他cpan包,看看是否有其他人已经为您完成了繁重的工作。

查看文档

my $count = threads->list();
与你所说的相反,它应该起作用。您正在使用的线程版本的文档说明了什么?那么,您可以使用以下方法作为解决方法

my $count = () = threads->list();
提供限制并发性的方法:

my $sem = Thread::Semaphore->new(15); # max 15 threads
my @threads = map {
    # request a thread slot, waiting if none are available:
    $sem->down;
    threads->create(\&mySubName, @params)
} 0..100;
$_->join for @threads;
在你的职能中:

sub mySubName {
    do_stuff();
    # release slot:
    $sem->up;
}

顺便说一句,这是(字符串化)非常非常顺便说一句-请记住perl中的线程与其他编程语言中的线程不同-它们非常需要资源,因为每个线程都有所有变量的副本。它们在某些情况下仍然很有用,但在我必须进行并行化的每种情况下,分叉的效果都要好得多。这与你的问题没有直接关系,我只是想告诉你。:)什么版本的Perl?什么版本的线程?当我尝试使用threads->list()时,我得到以下结果:在@INC中找不到auto/threads/lists.al(@INC包含:C:\Program Files(x86)\ActiveState Komodo 3.5\lib\support\dbgp\perllib C:\Program Files(x86)\ActiveState Komodo 3.5\lib\support\dbgp\perllib C:/Perl/lib C:/Perl/site/lib。)在C:\path\main3.pl行508如果
threads->list()
返回一个列表,则可以比使用循环更容易地捕获长度……比如
$totalThreads=scalar(threads->list()),不是吗?好吧,这是一个输入错误,我用了threads->list()而不是threads->list(),但现在我运行这个$totalThreads;foreach my$thr(threads->list()){$totalThreads++;}打印“活动线程:”$全部线程。“\n”;我得到的是:在串联(.)中,对我print@jonathan,如果我使用scalar()方法,我会得到相同的消息:当我尝试打印count@Jonathan莱夫勒,不,要想知道列表的长度,你必须使用我用过的技巧。尽管如此,
thread->list
假定返回标量上下文中的线程数。OP必须有一个旧版本的threads.pm.Richard我认为这是可行的,我在脚本中实现了它,看起来它确实在控制我的最大线程数,有没有一种方法可以窥视信号量持有的当前值?因为我运行了它,但在运行了一段时间后,我的脚本挂起在
$sem->下我将线程数量降低到了5个,它工作得很好,仍然有7个线程,看起来程序在某个时候会暂停,不知道为什么。谢谢你的提示!您可以通过取消对对象本身的引用来获得信号量的货币值,该对象本身只是对最大值(默认值为1)减去其计数的幸运引用。因此,要获得当前未完成的线程数,请计算
$max-$$sem
。我们可以使用共享标量变量来计算正在运行的线程数吗?我的意思是在mySubName()的第一行,我们将计数器增加1,并在返回时将其减少1。我使用了Richard提出的信号量方法,但我尝试了这个方法,它确实给出了列表中实际线程的计数,谢谢!
my $sem = Thread::Semaphore->new(15); # max 15 threads
my @threads = map {
    # request a thread slot, waiting if none are available:
    $sem->down;
    threads->create(\&mySubName, @params)
} 0..100;
$_->join for @threads;
sub mySubName {
    do_stuff();
    # release slot:
    $sem->up;
}