2013-06-04 28 views
3

我必須在一個Perl腳本中完成幾項任務。最好不要使用forkthread如何在Perl中編寫並行程序?

  1. 任務A:每5秒向服務器發出HTTP請求。無限,不應該被阻止。如果得到:

    1. 'TASK',任務A將調用一個耗時的子進程,所以如何避免賦值執行阻塞任務A的循環?
    2. '暫停',暫停請求
    3. '更新',tell任務B接收任務B或任務C
  2. 任務B數據時做一些

  3. 化妝POST請求到服務器:每隔1分鐘做一次mysql請求,並依靠結果,將tell任務A做POST請求

  4. 任務C:接受套接字連接並且tell任務A或B做某事。

三個平行的不定式循環過程,並將相互溝通。我怎樣才能做到這一點?

+2

「fork」或therad有什麼問題?他們是爲這種東西而設計的。 – TrueY

+0

我實際上在這裏使用線程,因爲通過隊列的通信非常簡單,並且可以選擇非阻塞。如果你'叉',你可以通過管道(連接文件句柄)進行通信。如果您將每個任務放在單獨的腳本中,則可以使用命名管道或套接字。這是更復雜的。至少對於任務A,你會使用線程來實現非阻塞屬性(例如,執行請求的五個http工作者,足夠耗費時間的工作人員) – amon

+0

爲什麼1.4需要由任務A完成? – ikegami

回答

11

該設計沒有任何意義,並聲稱最好不要使用線程或子進程使得更沒有意義。

你有要求的三個來源:

  • 請求源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; 

但繼續使用線程隊列::。

+0

已更新的答案。 – ikegami

+1

+1有耐心寫一個比單個問題更適合的答案。謝謝。 –

相關問題