Perl:正确传递数组以供线程处理

Dir*_*uin 2 perl multithreading

我正在学习如何在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";
}
Run Code Online (Sandbox Code Playgroud)

当然,现在这已完全打破,不起作用.它导致此错误:

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
Run Code Online (Sandbox Code Playgroud)

我的目标是双重的:

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

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

任何指导和更正都非常受欢迎.

ike*_*ami 6

你存储的结果foreach@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();
}
Run Code Online (Sandbox Code Playgroud)