我可以在Perl中重复使用连接的线程吗?
我有运行多个线程,并推动他们到主题列表的模块。我可以在Perl中重复使用连接的线程吗?
例如:
#!/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';
谢谢!
不要担心递增线程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系统上的本地系统调用,所以它往往会得到更好的优化。
我基本上创建了自己的队列,但是我会考虑这个模块,因为它可能会简化一些事情。 – tjwrona1992 2014-09-19 15:46:15
它有内置的锁定语义,这使得它更加整洁。不一定更有效的头脑,但明确的代码有它自己的优点。特别是我喜欢'end()'选项 - 因为那么你的子循环中的'while循环将返回'undef'并退出。 – Sobrique 2014-09-19 15:48:19
你为什么要线程ID可以重复使用? – 2014-09-19 15:36:41
我想我真正想知道的是,如果所有的线程内存都是真正在“加入”时发布的。事实上,ID不断增加使得它看起来像旧线程仍然以某种方式在内存中,即使它们已经“加入”了。 – tjwrona1992 2014-09-19 15:42:53
线程ID递增与进程ID递增一样多的红色鲱鱼。也不意味着疲惫正在发生。 – Sobrique 2014-09-19 15:42:58