简体   繁体   English

Perl:如何将哈希推入子例程之外的数组中

[英]Perl: How to push a hash into an array that is outside of a subroutine

I originally experimented with trying to send a hash object through Thread::Queue, but according to this link , my versions of Thread::Queue and threads::shared is too old. 我最初尝试通过Thread :: Queue发送哈希对象,但是根据此链接 ,我的Thread :: Queue和thread :: shared版本太旧了。 Unfortunately, since the system I'm testing on isn't mine, I can't upgrade. 不幸的是,由于我要测试的系统不是我的,因此无法升级。

I then tried to use a common array to store my hashes. 然后,我尝试使用一个公共数组来存储我的哈希。 Here is the code so far: 这是到目前为止的代码:

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

However, at the end of the procedure, @out_array is always empty. 但是,在过程结束时, @out_array始终为空。 If I remove the threading parts of the script, then @out_array is correctly populated. 如果删除脚本的线程部分,则@out_array正确填充。 I suspect I'm implementing threading incorrectly here. 我怀疑我在这里错误地实现了线程。

How would I correctly populate @out_array in this instance? 在这种情况下,我如何正确填充@out_array

You need to make it shared 您需要使其共享

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

I don't think you need to lock it if all you do is push onto it, but if you did, you'd use 我认为只要将其推入就不需要锁定它,但是如果您这样做了,则可以使用

 lock @out_array;

You need to share any array or hash referenced by a value you push onto it using the tools in thread::shared. 您需要共享使用thread :: shared中的工具将值推入的任何数组或哈希引用。

 push @out_array, share(%hash);

Though as I mentioned earlier, I'd use a Thread::Queue. 尽管如前所述,我将使用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();

Note that lack of anything thread-specific in test2. 请注意,在test2中缺少任何特定于线程的内容。 This is good. 很好 You should always strive for separation of concerns. 您应该始终努力分离关注点。

You need to return your data from thread: 您需要从线程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;
}

I found my answer in the example here . 我在这里的示例中找到了答案。

I had to change 2 things: 我必须更改2件事:

  • share the @out_array outside both subs 在两个潜艇之外共享@out_array
  • share the %hash in test2 test2共享%hash
  • add return; 增加return; to the end of test2 test2的结尾

Code outside both subs: 两个子代码之外的代码:

my @out_array : shared = ();

test2 sub: test2子:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM