好了,回溯了一下 - threads::shared
確實「單一數據結構」並沒有真正支持更復雜的東西。這是因爲當你'線程'時,你實際上創建了具有(某些)共享內存空間的獨立程序實例,但實際上每個'線程'都是一個單獨的程序。
因此,支持共享一個對象變得非常混亂。我發現更好的方法是......不是。使用Thread::Queue
在線程之間傳遞數據,並有一個線程用於整理結果。如果您需要傳遞更復雜的數據結構,則可以使用Storable
和freeze
/thaw
來串行化對象,並使用enqueue
它。
這樣你就不必擔心跳過共享嵌套數據結構 - 而且很有可能你會這樣做,因爲在對象上沒有「深度共享」選項 - 你必須明確地使用share
每個內部數組/散列(引用)。
所以我會解決它像這樣:
#!/usr/bin/perl
use strict;
use warnings;
package Test_Object;
sub new {
my ($class, $id) = @_;
my $self = {};
$self->{id} = $id;
bless $self, $class;
return $self;
}
sub set_result {
my ($self, $result_code) = @_;
$self->{result} = $result_code;
}
sub get_id {
my ($self) = @_;
return $self->{id};
}
sub get_result {
my ($self) = @_;
return $self->{result};
}
package main;
use strict;
use warnings qw/ all /;
use threads;
use Thread::Queue;
use Storable qw/ freeze thaw/;
my $work_q = Thread::Queue->new();
my $result_q = Thread::Queue->new();
sub worker {
my $tid = threads->self->tid;
print "$tid: starting\n";
while (my $item = $work_q->dequeue()) {
my $object = thaw($item);
print "$tid: got object with ID of ", $object->get_id, "\n";
$object->set_result($object->get_id . " : $tid");
$result_q->enqueue(freeze $object);
}
}
sub collator {
while (my $result = $result_q->dequeue) {
my $object = thaw $result;
print "Collator got object with result code of ", $object->get_result,
"\n";
}
## do something with collated wossnames - pass back to main maybe?
}
my @workers;
for (1 .. 5) {
my $thr = threads->create(\&worker);
push @workers, $thr;
}
my $collator = threads->create(\&collator);
for (1 .. 200) {
my $work_object = Test_Object->new($_);
$work_q->enqueue(freeze $work_object);
}
$work_q->end;
foreach my $thr (@workers) {
$thr->join;
}
$result_q->end;
foreach my $thr (threads->list) {
$thr->join;
}
我很欣賞的響應。 「Thread :: Queue」的文檔說如果對象的類不支持共享,則在隊列上傳遞對象可能不起作用。有關更多信息,請參閱threads :: shared中的BUGS AND LIMITATIONS。 傳遞包含對象的數組/散列引用對於5.10.0之前的Perl可能無效。它看起來像我與我受祝福的物體一樣的限制。不幸的是,這個應用程序仍然在Perl 5.8.8上。 –
無法弄清楚如何使用此評論編輯器製作換行符。 –
你沒有傳遞對象。您將序列化對象作爲標量傳遞。 – Sobrique