2

我正在学习如何在 Perl 中进行线程化。我在这里查看了示例代码并稍微修改了解决方案代码:

#!/usr/bin/perl
use strict;
use warnings;
use threads;
use Thread::Semaphore;

my $sem = Thread::Semaphore->new(2); # max 2 threads
my @names = ("Kaku", "Tyson", "Dawkins", "Hawking", "Goswami", "Nye");
my @threads = map {
    # request a thread slot, waiting if none are available:
    foreach my $whiz (@names) {
        $sem->down;
        threads->create(\&mySubName, $whiz);
    }
} @names;

sub mySubName {
    return "Hello Dr. " . $_[0] . "\n";
    # release slot:
    $sem->up;
}

foreach my $t (@threads) {
    my $hello = $t->join();
    print "$hello";
}

当然,现在这完全被打破了,并且不起作用。它导致此错误:

C:\scripts\perl\sandbox>threaded.pl
Can't call method "join" without a package or object reference at C:\scripts\perl\sandbox\threaded.pl line 24.
Perl exited with active threads:
        0 running and unjoined
        9 finished and unjoined
        0 running and detached

我的目标有两个:

  • 强制在任何给定时间允许的最大线程数
  • 为要使用的线程提供“工作”数组

在最初的解决方案中,我注意到0..100;代码似乎指定了分配给线程的“工作量”。但是,在我想提供一系列工作的情况下,我还需要提供类似的东西吗?

非常欢迎任何指导和更正。

4

1 回答 1

6

您将结果存储为foreachinto@threads而不是threads->create.

即使你解决了这个问题,你收集完成的线程也太晚了。我不确定这是一个多大的问题,但它可能会阻止在某些系统上启动超过 64 个线程。(64 是程序在某些系统上一次可以拥有的最大线程数。)

更好的方法是重用你的线程。这解决了您的两个问题并避免了重复创建线程的开销。

use threads;
use Thread::Queue 3.01 qw( );

use constant NUM_WORKERS => 2;

sub work {
   my ($job) = @_;
   ...
}

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

   for (1..NUM_WORKERS) {
      async {
         while (my $job = $q->dequeue()) {
            work($job);
         }
      };
   }

   $q->enqueue(@names);  # Can be done over time.
   $q->end();            # When you're done adding.
   $_->join() for threads->list();
}
于 2013-07-14T03:27:03.787 回答