以下是我正在研究的一个简单的代码示例。它只是启动一个线程,等待5秒,然后终止它。
#!/usr/bin/perl
use strict;
use warnings;
use threads;
sub thread_sub
{
threads->create(sub
{
sleep 5; # HERE A WHILE ROUTINEs EMULATED BY SLEEP
threads->detach();
});
}
thread_sub();
exit;
但结果是:
# ./multithread.pl
Perl exited with active threads:
1 running and unjoined
0 finished and unjoined
0 running and detached
这是因为它运行线程但在退出之后没有等待。
那么,我怎样才能在退出前等待线程完成?我知道有is_running
,但我不知道如何在我的代码中实现它。遗憾的是,报告的代码只是一个了解如何实现is_running的示例。谢谢。
答案 0 :(得分:5)
要等待线程完成,通常会使用以下内容:
$thread->join();
要等待所有线程,可以使用以下内容:
$_->join() for threads->list();
如果这是你要做的事情,不要分离线程。
关于detach
...
如果您有即发即弃的线程,可以使用
use threads;
use threads::shared;
my $thread_count :shared = 0;
sub thread_sub {
{ lock $thread_count; ++$thread_count; cond_signal($thread_count); }
my $thread = async {
sleep 5;
{ lock $thread_count; --$thread_count; cond_signal($thread_count); }
};
$thread->detach(); # Free the small thread object as soon as it completes.
}
thread_sub();
# When it's time to exit:
{ lock($thread_count); cond_wait($thread_count) while $thread_count != 0; }
但是,仅仅加入线程并没有多大帮助,这更加简单。
use threads;
sub thread_sub {
async {
sleep 5;
};
}
thread_sub();
# Periodically:
$_->join() for threads->list(threads::joinable);
# When it's time to exit:
$_->join() for threads->list();
最后,在实践中更常见的是创建一个线程池并重用它们,而不是随时创建线程,因为Perl中的线程创建很昂贵。在这种情况下,分离更没意义。
use threads;
use Thread::Queue qw( ); # 3.01+
use constant NUM_WORKERS => 3;
sub process_job { sleep 5 }
my $q = Thread::Queue->new();
for (1..NUM_WORKERS) {
async {
while (my $job = $q->dequeue()) {
process_job($job);
}
};
}
$q->enqueue('some_job');
# When it's time to exit:
$q->end();
$_->join() for threads->list();
我还没有使用它,但请查看Thread::Pool。
顺便说一下,async { ... }
只是一种更清晰的说法threads->create(sub { ... })
。
答案 1 :(得分:1)
你为什么要这样做?脱离线程意味着你不关心关于它的回归或命运;当程序即将退出时,它将完成并退出或被杀死。
如果你想等不及detach
,join
。
关于如何使用is_running
的问题,您需要一个线程对象
use warnings;
use strict;
use feature 'say';
use threads;
$| = 1;
sub thread_sub
{
my $thr = threads->create(sub
{
## threads->detach();
sleep 2; say "\tprocessing ..";
sleep 2; say "\tdone";
});
return $thr;
}
my $thr = thread_sub();
while ($thr->is_running) { # or: while (threads->list)
sleep 1;
say "main";
}
$_->join for threads->list; # instead of detaching
say "done";
顺便说一下,is_running
(或list
)也涵盖了一个分离的主题,上面的内容也适用。但这样做并没有意义;我只是在讨论你问的方法。