如何检测线程是否正在运行

时间:2017-10-27 05:37:26

标签: multithreading perl

以下是我正在研究的一个简单的代码示例。它只是启动一个线程,等待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的示例。谢谢。

2 个答案:

答案 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)

你为什么要这样做?脱离线程意味着你不关心关于它的回归或命运;当程序即将退出时,它将完成并退出或被杀死。

如果你想等不及detachjoin

关于如何使用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)也涵盖了一个分离的主题,上面的内容也适用。但这样做并没有意义;我只是在讨论你问的方法。