简体   繁体   中英

How do I detect if thread/s is running

The following is a simple code example I'm working on. It just starts a thread, wait 5 seconds, and then terminate it.

#!/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;

But the result is:

# ./multithread.pl 
Perl exited with active threads:
        1 running and unjoined
        0 finished and unjoined
        0 running and detached

This because it runs the thread but after that exit without waiting. So, how can I wait for thread to finish before exit? I know there is is_running , but I don't known how to implement it in my code. Obliviously the reported code is just an example to understand how to implement is_running. Thank you.

To wait for a thread to finish, one typically uses the following:

$thread->join();

To wait for all threads, one would therefore use the following:

$_->join() for threads->list();

Don't detach the thread if this is what you are going to do.


About detach ...

If you had fire-and-forget threads, you could use

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; }

But that doesn't gain you much over just joining the threads, which is far simpler.

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();

Finally, it's more common in practice to create a pool of threads and reuse them rather then creating threads on the fly because thread creation is expensive in Perl. In this situation, detaching makes even less sense.

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();

I haven't used it, but look into Thread::Pool .


By the way, async { ... } is just a cleaner way of saying threads->create(sub { ... }) .

Why are you doing this? Detaching a thread means that you don't care about its return or fate; it will finish and exit or be killed as the program is about to exit.

If you want to wait for it don't detach but join .


As for the question of how to use is_running , you need a thread object

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";

Btw, a detached thread is also covered by is_running (or list ) and the above works for it as well. But doing that doesn't make sense; I am just discussing the method you ask about.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM