在perl

时间:2019-04-03 18:47:36

标签: multithreading perl thread-safety

我正在编写一个程序包,它接受诸如线程数,thread :: Queue对象之类的输入。 创建包对象后,我将基于输入参数创建线程,并在每个线程中使输入队列出队,并且每个线程执行一个简单的unix命令,例如对服务器执行ping操作(为保持简单而进行了更改)。 下面是代码:

my $failed_q = Thread::Queue -> new();
my $success_q = Thread::Queue -> new();
my $process_q = Thread::Queue -> new();

package WorkerThreads;


sub new {
   my $class = shift;
   my $self = {
      _ThreadCount => shift,
      _FidQueue => shift,
      _SuccessQueue  => shift,
      _FailedQueue => shift,
   };
   bless $self, $class;
   return $self;
}

sub WorkerProcess
{
  my ($self)=@_;

  while ( my $fid = $self->{_FidQueue} -> dequeue() )
  {
    chomp ( $fid );
    print threads -> self() -> tid(). ": pinging $fid\n";
    my $result = `/bin/ping -c 1 $fid`;
    if ( $? ) { $self->{_FailedQueue} -> enqueue ( $fid ) }
    else { $self->{_SuccessQueue} -> enqueue ( $fid ) ; }
    sleep 1;
  }
 print threads -> self() -> tid(). ":\n";
}


sub CreateThreads
{
    my ($self)=@_;
    my $Num_of_threads=$self->{_ThreadCount};

    for ( 1..$Num_of_threads )
    {
      threads -> create ( \&WorkerProcess );
    }

}

sub StartThreads
{
my ($self)=@_;

    foreach my $thr ( threads -> list() )
    {
      $thr -> join();
    }
}

sub PrintResult
{
my ($self)=@_;


     while ( my $fid = $self->{_FailedQueue} -> dequeue_nb() )
     {
       print "$fid failed to ping\n";
     }

     #collate results. ('synchronise' operation)

     while ( my $fid = $self->{_SuccessQueue} -> dequeue_nb() )
     {
       print "$fid Ping Succeeded\n";
     }

}
sub ProcessRequest
{
 my ($self)=@_;

 $self->CreateThreads(@_);
 $self->StartThreads(@_);
 $self->PrintResult(@_);

}

package main;

#insert tasks into thread queue.
open ( my $input_fh, "<", "server_list" ) or die $!;
$process_q->enqueue( <$input_fh> );
close ( $input_fh );


my $Workers;

$Workers=WorkerThreads->new(
                            10,
                            $process_q,
                            $success_q, 
                            $failed_q
                          );

$Workers->ProcessRequest();

当我尝试在while循环中出队队列未定义时遇到错误。所以我有这样的疑问,比如我们可以将线程队列对象作为参数传递给程序包。

Thread 1 terminated abnormally: Can't call method "dequeue" on an undefined value at .

1 个答案:

答案 0 :(得分:2)

您要将函数传递到threads->create中,而没有它们在其中处理哪个对象的任何上下文。这样的事情应该起作用

threads->create( sub { $self->WorkerProcess } );