如何在Perl中按需启动线程?

3
在C#中,我们可以像以下这样根据需要创建线程并启动线程(如果我没记错的话)。
Thread th=new thread("function");
th.start()

但是在Perl中,当我创建它本身时,它已经开始运行了。例如:

$thread1=thread->create("function");

但是我想创建4个线程。我应该只在需要时启动它们。并且我必须检查它们是否正在运行?如果线程没有运行,则我必须通过传递不同的参数来启动相同的线程。如何在Perl中实现这一点?


http://perldoc.perl.org/Thread/Queue.html - mpapec
如何在不使用队列的情况下完成这个任务? - user3035874
如果您想要重复使用现有的线程,那么工作线程和主线程之间应该有某种通信方式,而队列就可以实现这一点。 - mpapec
谢谢你的努力。我没有找到任何简单的例子。你能否用简单的3个线程使用thread::queue来发布你的答案? - user3035874
3个回答

2

可以将多个作业发送到队列中,它们正在等待轮流传递给工作程序。

use strict;
use warnings;
use threads;
use Thread::Queue;

my $no_of_workers = 4;
my $q = Thread::Queue->new();
# Worker thread
my @thr = map {

  my $t = threads->create(sub{

    # Thread will loop until no more work
    while (defined(my $item = $q->dequeue())) {
        # Do work on $item
        print "$item\n";
    }
  });

  {queue => $q, thread => $t, id => $_};

} 1 .. $no_of_workers;


# Send work to each thread
$_->{queue}->enqueue("Job for thread $_->{id}") for @thr;

for (@thr) {
  # Signal that there is no more work to be sent
  # $_->{queue}->end();

  # similar to $queue->end() for older perl
  $_->{queue}->enqueue(undef) for @thr;

  # wait for threads to finish
  $_->{thread}->join();
}

将工作以环形方式分配给工人,编号为0..19

for my $i (0 .. 19) {
  my $t = $thr[$i % @thr]; # $i % @thr => 0,1,2,3, 0,1,2,3, ..
  $t->{queue}->enqueue("Job for thread $t->{id}");
}

我在哪里可以将子程序发送为工作?我应该在哪一行添加? - user3035874
抱歉打扰您了。我是 Perl 的新手。 - user3035874
谢谢。完成任务后,如何再次为这4个线程分配4个任务? - user3035874
我理解的是,有4个线程分别执行4个任务。当它们完成任务后,我想再次为它们分配4个任务。如何实现?实际上,我有20个任务。我想用4个线程重复执行这20个任务5次。我的表述正确吗? - user3035874
非常感谢您 :-)。我想让您确认一件事。您是说 $thr [0] 表示第一个线程,$thr [1] 表示第二个线程吗? - user3035874
显示剩余7条评论

0

你不想为每个线程都创建一个队列!这样即使有可用的工作,你也最终会得到空闲的线程。

use strict;
use warnings;

use threads;

use Thread::Queue 3.01 qw( );

use constant NUM_WORKERS => 4;

sub worker {
   my ($job) = @_;
   print("Job: $job\n");
   sleep(rand(4));  # Pretending to do $job
}

{
   my $q = Thread::Queue->new();

   for (1..NUM_WORKERS) {
      async {
         while (defined(my $item = $q->dequeue())) {
            worker($item);
         }
      };
   }

   # Give the workers work to do.
   $q->enqueue($_) for 1..14;

   # When you're done adding, wait for the workers to finish.
   $q->end();
   $_->join() for threads->list;
}

我应该在哪里调用我的子程序以便于我的线程?我需要将子程序调用放在print("Job: $job\n");中吗? - user3035874
我在这段代码中遇到了严重的问题。如果一个线程停止,其他线程会自动停止。 - user3035874
关于“同样的错误出现了,这是我旧代码收到的错误。在第114行将1faa7a8释放到错误的池子中,而不是3f4c20”,我的代码并没有114行,所以我不知道你为什么告诉我那个。 - ikegami
关于“如果一个线程停止,其他线程会自动停止”的说法,我不知道这是什么意思。“停止”并不是线程可以做的事情。 - ikegami
关于“在哪里调用我的子程序来运行线程?”worker就是你的子程序。 - ikegami

0

这段代码只处理了4个线程,然后就停止了。它没有处理队列中剩下的6个项目。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接