2013-07-14 42 views
1

我最初试图通过Thread :: Queue发送散列对象,但根据this link,我的Thread :: Queue和threads版本: :共享太旧了。不幸的是,由于我正在测试的系统不是我的,我无法升级。Perl:如何将散列推入子例程之外的数组

然后我尝试使用一个通用数组来存储我的哈希值。这是迄今为止代码:

#!/usr/bin/perl 
use strict; 
use warnings; 

use threads; 
use Thread::Queue; 
use constant NUM_WORKERS => 10; 

my @out_array; 
test1(); 

sub test1 
{ 
    my $in_queue = Thread::Queue->new(); 
    foreach (1..NUM_WORKERS) { 
     async { 
      while (my $job = $in_queue->dequeue()) { 
       test2($job); 
      } 
     }; 
    } 

    my @sentiments = ("Axe Murderer", "Mauler", "Babyface", "Dragon"); 

    $in_queue->enqueue(@sentiments); 
    $in_queue->enqueue(undef) for 1..NUM_WORKERS; 
    $_->join() for threads->list(); 

    foreach my $element (@out_array) { 
     print "element: $element\n"; 
    } 
} 

sub test2 
{ 
    my $string = $_[0]; 
    my %hash = (Skeleton => $string); 
    push @out_array, \%hash; 
} 

然而,在手术结束时,@out_array总是空的。如果我删除脚本的线程部分,则@out_array正确填充。我怀疑我在这里错误地执行了线程。

在这种情况下,我该如何正确填充@out_array

回答

2

你需要使它共享

use threads::shared; 
my @out_array :shared; 

我不认为你需要锁定它,如果你做的是推到它,但如果你这样做,你会使用

lock @out_array; 

你需要共享任何数组或哈希引用的值,你推到它使用了thread :: shared中的工具。

push @out_array, share(%hash); 

虽然如前所述,我会使用一个Thread :: Queue。

sub test2 { 
    my ($string) = @_; 
    my %hash = (Skeleton => $string); 
    return \%hash; 
} 

... 

my $response_q = Thread::Queue->new() 
my $running :shared = NUM_WORKERS; 

... 

    async { 
     while (my $job = $request_q->dequeue()) { 
      $response_q->enqueue(test2($job)); 
     } 

     { lock $running; $response_q->enqueue(undef) if !--$running; } 
    }; 

... 

$request_q->enqueue(@sentiments); 
$request_q->enqueue(undef) for 1..NUM_WORKERS; 

while (my $response = $response_q->dequeue()) { 
    print "Skeleton: $response->{Skeleton}\n"; 
} 

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

请注意缺少test2中任何线程特定的内容。这很好。你应该始终努力分离关注点。

+0

你在我做之前只回答了几秒钟。谢谢:) –

+0

我喜欢用“q”作为“队列”,因为它们听起来一样[除非你像我一样用法语发音“队列”)] – ikegami

+0

修正了一个错误。 (它永远阻塞响应队列。) – ikegami

0

您需要从线程return数据:

.... 
     async { 
      my $data; 
      while (my $job = $in_queue->dequeue()) { 
       $data = test2($job); 
      } 

      return $data; 
     }; 
... 

for (threads->list()) { 

    my $data = $_->join(); 
    #now you have this thread return value in $data 
} 

sub test2 
{ 
    my $string = $_[0]; 
    my %hash = (Skeleton => $string); 
    return \%hash; 
} 
+0

由于线程队列的::版本我使用,我不能从队列中返回一个哈希值。我只能返回字符串。 –

+0

我的代码从线程返回它,但不是排队...... – gangabass

0

我在示例here中找到了我的答案。

我不得不改变两两件事:

  • 份额@out_array两个潜艇外
  • 份额%hashtest2
  • 添加return;test2

码外两端目录:

my @out_array : shared =(); 

test2子:

sub test2 
{ 
    my $string = $_[0]; 
    my %hash : shared; 
    $hash{Skeleton} = $string; 
    push @out_array, \%hash; 
    return; 
}