这种设计毫无意义,并且声称最好不要使用线程或子进程的说法更没有意义。
您有三个请求来源:
- 请求源 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。