該設計沒有任何意義,並聲稱最好不要使用線程或子進程使得更沒有意義。
你有要求的三個來源:
- 請求源A:使Web請求,每5秒一個服務器。
- 請求源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;
但繼續使用線程隊列::。
「fork」或therad有什麼問題?他們是爲這種東西而設計的。 – TrueY
我實際上在這裏使用線程,因爲通過隊列的通信非常簡單,並且可以選擇非阻塞。如果你'叉',你可以通過管道(連接文件句柄)進行通信。如果您將每個任務放在單獨的腳本中,則可以使用命名管道或套接字。這是更復雜的。至少對於任務A,你會使用線程來實現非阻塞屬性(例如,執行請求的五個http工作者,足夠耗費時間的工作人員) – amon
爲什麼1.4需要由任務A完成? – ikegami