我有一个运行多个线程的模块,并将它们推送到线程列表中。
例如:
#!/usr/bin/perl
#test_module.pm
package test_module;
use strict;
use warnings;
use threads;
sub main {
my $max_threads = 10;
my @threads = ();
# create threads
while (scalar @threads < $max_threads) {
my $thread = threads->new(\&thread_sub);
push @threads, $thread;
}
# join threads
for my $thread (@threads) {
$thread->join();
}
}
sub thread_sub {
my $id = threads->tid();
print "I am in thread $id\n";
}
1;
问题是我从一个Perl脚本多次调用此模块,而不是消除旧线程并创建新线程,线程ID只是保持递增。我听说如果你没有正确摆脱Perl中的旧线程,这将导致内存泄漏并减慢程序速度,这是真的吗?来自旧线程的数据是否只是占用内存空间?
如果是这样,这可能会成为一个大问题,因为我的脚本将成为一个更大的程序的一部分,可能会生成数百或数千个线程,所有这些线程即使在完成使用后也会占用内存。我怎么能阻止这种情况发生?我的线程可以重复使用吗?
这是一个示例脚本,它将调用模块并显示线程将如何继续递增,即使我加入了旧线程(我认为“加入”是你在他们之后清理的方式,我做错了什么? )这个脚本的使用方式我不能从占用空间的旧线程中获取内存。
例如:
#!/usr/bin/perl
#testing.pl
use strict;
use warnings;
use test_module;
test_module::main();
test_module::main();
test_module::main();
system 'pause';
谢谢!
答案 0 :(得分:3)
不要担心线程ID递增 - 这并不意味着正在运行的线程数正在增加。一旦线程join
,它就已经完成执行并被终止。
然而,不断重新生成的线程也不理想 - 在perl中创建线程不是特别轻量级的操作。因此,如果您必须做类似的事情,并且特别关注效率 - 请转而fork()
。
我发现我倾向于使用{工作线程'模型,使用Thread::Queue
:
my $processing_q = Thread::Queue -> new();
sub worker_thread {
while ( my $item = $processing_q -> dequeue() ) {
# do stuff to $item
}
}
for ( 1 .. $num_threads ) {
my $thr = threads -> create ( \&worker_thread );
}
$processing_q -> enqueue ( @generic_list_of_things );
$processing_q -> end;
foreach my $thread ( threads -> list() ) {
$thread -> join();
}
这会将一批项目输入到队列中,并且您的工作线程将一次处理一个项目 - 这意味着您可以运行合理的数字,而无需不断重新生成。
作为替代方案 - 看看Parallel::ForkManager
- fork样式并行处理最初可能看起来违反直觉,但fork()
是Unix系统上的本机系统调用,因此它往往更好地进行优化。