2014-01-14 17 views
0

我有這樣的測試腳本:使用線程到Perl的面向對象的封裝

use threads; 

start(); 

sub start { 
    my $A = threads->create(\&A); 
    my $B = threads->create(\&B); 
    sleep; 
} 

sub A { 
    while (1) { 
    print "A\n"; 
    sleep(1); 
    } 
} 

sub B { 
    while (1) { 
    print "B\n"; 
    sleep(1); 
    } 
} 

這個輸出是(每秒一次,永遠):

A 
B 

我試圖做

package Test; 
use threads; 

sub new { my ($class) = @_; 
    my $self = { 
    A => undef, 
    B => undef 
    }; 
    bless $self, $class; 
    return $self; 
} 

sub start { my ($self) = @_; 
    $self->{A} = threads->create(\&{$self->A}); 
    $self->{B} = threads->create(\&{$self->B}); 
    sleep; 
} 

sub A { my ($self) = @_; 
    while (1) { 
    print "A\n"; 
    sleep(1); 
    } 
} 

sub B { my ($self) = @_; 
    while (1) { 
    print "B\n"; 
    sleep(1); 
    } 
} 

1; 

然後:

與面向對象的包相同的
use Test; 

my $test = Test->new(); 

$test->start(); 

這個輸出是(每秒一次,永遠):

A 

好像代碼卡的第一個線程上。我很難理解Perl中線程背後的邏輯。如何從面向對象包中的第一個腳本複製相同的行爲?

+0

第一個例子中的'start'例程應該在每個線程上使用invoke'join'而不是永久休眠。 –

+0

我同意。我用'sleep',因爲我不得不輸入= P – calvillo

回答

1

$self->A是一個永不返回的方法調用,因此\&{$self->A}也永遠不會返回,並且您永遠不會定義$self->{B}

一種方式做到這一點會是

$self->{A} = threads->create(sub { $self->A }); 
$self->{B} = threads->create(sub { $self->B }); 

表達sub { $self->A }限定(匿名)子程序和把它傳遞給threads::create方法,但不調用子程序,允許程序繼續進行。

+0

謝謝。這是問題所在。我試過'$ self - > {A} = threads-> create(\&A,$ self);'。這似乎也起作用。 – calvillo

+1

'threads-> create(\&A,$ self)'的問題是子'A'沒有被「作爲方法調用」。這意味着類「Test」的子類將無法覆蓋該方法。根據@暴徒的建議,使用'threads-> create(sub {$ self-> A})''。 – tobyink

0

這是一個更有趣的測試腳本。

您應該通過關閉匿名子例程中的實例來調用對象實例上的方法。

我不知道你想與threads->create{\&{$self->A}};

create之前實現可調用什麼,調用$self->A必須返回一個值。但是,它的設計永遠不會回來。但是,那麼,你也應該在你的create調用中包含大括號。所以,至少可以說這是令人困惑的。

此外,請不要嘗試通過犧牲代碼的可讀性來節省行數。

package Test; 
use strict; 
use warnings; 
use threads; 

sub new { 
    my $class = shift; 
    return bless { A => undef, B => undef } => $class; 
} 

sub start { 
    my $self = shift; 
    $self->{$_} = threads->create(sub { $self->$_ }) for qw(A B); 
    $self->{$_}->join for qw(A B); 
    return; 
} 

sub A { 
    my $i = 'A'; 
    while (10 > time - $^T) { 
     print "$i\n"; 
     $i++; 
     sleep 1; 
    } 
} 

sub B { 
    my $i = '0'; 
    while (10 > time - $^T) { 
     print "$i\n"; 
     $i++; 
     sleep 1; 
    } 
} 

package Main; 

use strict; 
use warnings; 

my $test = Test->new; 
$test->start; 
+0

我正在從6個不同的進程下載信息的機器人上工作。它已經可以工作了,但是我想讓它作爲一個對象工作,這樣我可以根據需要使用機器人的多個實例。關於大括號,這是一個錯字;關於易讀性......我想這就是我讀取參數的方式,對嗎? – calvillo

+0

當你寫'sub start {my($ self)= @_;'時,很容易錯過賦給'$ self'的聲音。至少我做了。 –