1

我最初尝试尝试通过 Thread::Queue 发送哈希对象,但根据此链接,我的 Thread::Queue 和 threads::shared 版本太旧了。不幸的是,由于我正在测试的系统不是我的,我无法升级。

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

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

4

3 回答 3

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 中缺少任何特定于线程的内容。这很好。您应该始终努力实现关注点分离。

于 2013-07-14T16:00:16.600 回答
0

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

我不得不改变两件事:

  • 共享@out_array外部两个潜艇
  • 分享%hash_test2
  • 添加return;到末尾test2

两个潜艇之外的代码:

my @out_array : shared = ();

test2子:

sub test2
{
    my $string = $_[0];
    my %hash : shared;
    $hash{Skeleton} = $string;
    push @out_array, \%hash;
    return;
}
于 2013-07-14T16:00:34.670 回答
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;
}
于 2013-07-14T15:29:48.850 回答