如何在Perl中编写并行程序?

时间:2013-06-04 05:52:22

标签: perl

我必须在一个Perl脚本中执行几项任务。最好不要使用forkthread

  1. 任务A:每5秒向服务器发出一次HTTP请求。无限,不应该被阻止。如果得到:

    1. 'TASK',任务A将调用一个耗时的子进程,那么如何避免赋值执行块任务A的循环?
    2. '暂停',暂停请求
    3. '更新',tell任务B做某事
    4. 从任务B或任务C
    5. 接收数据时向服务器发出POST请求
  2. 任务B:每1分钟发出一次mysql请求,并依赖于结果,tell任务A做POST请求

  3. 任务C:接受套接字连接,并tell任务A或B执行某些操作。

  4. 三个并行的不定式循环过程,并将相互通信。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:11)

这种设计没有任何意义,并且声称最好不使用线程或子进程的说法更不合理。

您有三个请求来源:

  • 请求来源A:每5秒向服务器发出一次Web请求。
  • 请求源B:每60秒向服务器发出一次数据库请求。
  • 请求来源C:接受来自套接字的请求。

为每个请求源创建一个线程。他们的工作仅仅是监控每个请求源,以确保在检查源时对其进行检查。因此,这些线程都不应该做任何实际的工作。如果必须执行任务,则将工作委派给工作线程。他们不发布任何东西。他们不会写入数据库。

实际任务(包括发送POST和写入数据库)由一个或多个工作线程(您的选择)执行。工作线程接收来自由三个请求源填充的单个Thread :: Queue队列的请求。


所以代码看起来像:

use threads;
use Thread::Queue qw( );

use constant NUM_WORKERS => 5;  # Tweak this. Can be as low as 1.

sub poll_web {
   my ($request_q) = @_;
   ... init ...
   while (1) {
      ...
      $request_q->enqueue([post => ...]);
      ...
   }
}

sub poll_db { ... }              # Just like poll_web

sub accept_connections { ... }   # Just like poll_web

sub post_handler { ... }         # Receives args passed to enqueue

{
   my $request_q = Thread::Queue->new();

   my %job_handlers = (
      post => \&post_handler,
      ...
   );

   for (1..NUM_WORKERS) {
      async {
         while (1) {
            my $job = $request_q->dequeue();
            my ($job_type, @args) = @$job;
            my $handler = $job_handlers{$job_type};
               or do { warn("Unknown job type $job_type"); next };
            $handler->(@args);
         }
      };
   }

   async { poll_web($request_q); };
   async { poll_db($request_q); };
   accept_connections($request_q);
}

如果要使用进程而不是线程,请更改

use threads;

use forks;

但继续使用Thread :: Queue。