好了,回溯了一下 - 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