gpt4 book ai didi

multithreading - 如何将 perl 子例程排队到线程队列而不是数据?

转载 作者:行者123 更新时间:2023-12-04 06:53:37 24 4
gpt4 key购买 nike

背景 :
在阅读如何对我的 perl 脚本进行多线程处理时,我阅读了(来自 http://perldoc.perl.org/threads.html#BUGS-AND-LIMITATIONS)

On most systems, frequent and continual creation and destruction of threads can lead to ever-increasing growth in the memory footprint of the Perl interpreter. While it is simple to just launch threads and then ->join() or ->detach() them, for long-lived applications, it is better to maintain a pool of threads, and to reuse them for the work needed, using queues to notify threads of pending work.



我的剧本将是长期存在的;它是一个始终运行的 PKI LDAP 目录监视守护程序。如果企业监控解决方案因任何原因停止运行,则会生成警报。我的脚本将检查我是否可以访问另一个 PKI LDAP 目录,并验证两者上的吊销列表。

问题 :我在谷歌上能找到的所有内容都显示将变量(例如标量)传递给线程队列而不是子例程本身......我想我只是不明白如何与实现线程的方式(没有队列)。

问题 1 : 我怎样才能“维护一个线程池”来避免 perl 解释器慢慢地吃掉越来越多的内存?
问题 2 :(无关,但虽然我发布了此代码)在主程序结束时是否有安全的 sleep 量,以便我不会在一分钟内多次启动线程? 60 似乎很明显,但是如果循环很快,或者由于处理时间或其他原因可能会错过一分钟,这是否会导致它运行多次?
提前致谢!
#!/usr/bin/perl

use feature ":5.10";
use warnings;
use strict;
use threads;
use Proc::Daemon;
#

### Global Variables
use constant false => 0;
use constant true => 1;
my $app = $0;
my $continue = true;
$SIG{TERM} = sub { $continue = false };

# Directory Server Agent (DSA) info
my @ListOfDSAs = (
{ name => "Myself (inbound)",
host => "ldap.myco.ca",
base => "ou=mydir,o=myco,c=ca",
},
{ name => "Company 2",
host => "ldap.comp2.ca",
base => "ou=their-dir,o=comp2,c=ca",
}
);
#

### Subroutines

sub checkConnections
{ # runs every 5 minutes
my (@DSAs, $logfile) = @_;
# Code to ldapsearch
threads->detach();
}

sub validateRevocationLists
{ # runs every hour on minute xx:55
my (@DSAs, $logfile) = @_;
# Code to validate CRLs haven't expired, etc
threads->detach();
}

#

### Main program
Proc::Daemon::Init;

while ($continue)
{
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);

# Question 1: Queues??

if ($min % 5 == 0 || $min == 0)
{ threads->create(&checkConnections, @ListOfDSAs, "/var/connect.log"); }

if ($min % 55 == 0)
{ threads->create(&validateRevocationLists, @ListOfDSAs, "/var/RLs.log"); }

sleep 60; # Question 2: Safer/better way to prevent multiple threads being started for same check in one matching minute?
}

# TERM RECEIVED
exit 0;
__END__

最佳答案

use threads;
use Thread::Queue 3.01 qw( );

my $check_conn_q = Thread::Queue->new();
my $validate_revoke_q = Thread::Queue->new();

my @threads;
push @threads, async {
while (my $job = $check_conn_q->dequeue()) {
check_conn(@$job);
}
};
push @threads, async {
while (my $job = $validate_revoke_q->dequeue()) {
validate_revoke(@$job);
}
};

while ($continue) {
my ($S,$M,$H,$m,$d,$Y) = localtime; $m+=1; $Y+=1900;

$check_conn_q->enqueue([ @ListOfDSAs, "/var/connect.log" ])
if $M % 5 == 0;

$validate_revoke_q->enqueue([ @ListOfDSAs, "/var/RLs.log" ])
if $M == 55;

sleep 30;
}

$check_conn_q->end();
$validate_revoke_q->end();
$_->join for @threads;

我不确定这里是否需要并行化。如果不是,你可以简单地使用
use List::Util qw( min );

sub sleep_until {
my ($until) = @_;
my $time = time;
return if $time >= $until;
sleep($until - $time);
}

my $next_check_conn = my $next_validate_revoke = time;
while ($continue) {
sleep_until min $next_check_conn, $next_validate_revoke;
last if !$continue;

my $time = time;
if ($time >= $next_check_conn) {
check_conn(@ListOfDSAs, "/var/connect.log");
$next_check_conn = time + 5*60;
}

if ($time >= $next_validate_revoke) {
validate_revoke(@ListOfDSAs, "/var/RLs.log");
$next_validate_revoke = time + 60*60;
}
}

关于multithreading - 如何将 perl 子例程排队到线程队列而不是数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16215502/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com