2014-03-06 71 views
1

這可能是一個Perl的專家一個簡單的問題 -Perl的多個子程序

我試圖運行一個腳本,理應做到這一點>

Main 
{ 
While (true) 
    Call Sub A 
    Call Sub B 
    Call Sub C 
} 

Sub A 
{ 
Go execute a method A for whatever it needs to do --- 
before next time method A runs it need to wait atleast 60 seconds but i still want to call method B in these 60 seconds. 
} 

Sub B 
{ 
    Go execute a method B for whatever it needs to do --- 
before next time method b runs it need to wait atleast 60 seconds but i still want to call method C in these 60 seconds in mean time. 

} 

Sub C 
{ 
    Go execute a method C for whatever it needs to do --- 
before next time method C runs it need to wait atleast 60 seconds at this moment control should be back in Main and wait for first 60 seconds of A to expire so that Sub A can be called 
} 

我的問題: 問:什麼是最好的和優化的方式,我可以做到這一點 - ?

問:如果我在每個子再下一子就不會被調用,甚至直到60秒把睡眠60到期,就會耽誤整個處理。

問:我想3級潛艇稱爲每60秒的順序

Q最後,如果我需要調用2級潛艇在每60秒和最後一個子每隔一小時 - 我該怎麼做呢?

評論 - 我的想法是把UTC作爲一個變量,並將其存儲在一個變量,並保持檢查的時間,如果時間過期不是打電話個別潛艇,但不知道是否運行的代碼它最佳的方式。

+1

執行子程序每次取多秒?總和總是小於60秒?如果A在60秒內完成但B尚未完成,A應該再次運行嗎?那麼C呢?您可以使用多個線程,所以有一個運行的A-線程在沒有更大的頻率,每60秒一次,和B-線程B和C型線對C? –

+0

使用線程可能是去這裏,但請記住,如果你的潛艇與普通的全局變量混合的方式(全球在不僅在各個子),你必須確保沒有兩個線程試圖修改同變量在同一時間。這不是一項微不足道的任務。 – DeVadder

+0

因此,從理論上講,任何時間都不應該超過幾秒(這些是SOAP調用),而我的測試顯示它可能需要很少的秒數,絕對總和不會等於或超過60秒。但我又想採取最佳實踐,而不是依靠我的想法.....所以我可以使用多線程程序(我不知道如何?)我需要一些僞代碼的幫助,如果可能的話在Perl中。並解釋它將如何工作......感謝並感謝您的迴應。 – Nik

回答

1

你可能想use threads。以下片段可能會給你一個起點。既然你有四個Qs的而不是一個,我不會細講爲他們每個人。

#!/usr/bin/perl 

use warnings; 
use strict; 
use threads; 

my @t = (
    threads->create(\&A), 
    threads->create(\&B), 
    threads->create(\&C) 
); 

$t[0] -> join(); 
$t[1] -> join(); 
$t[2] -> join(); 

sub A { 
    for my $i (1 .. 10) { 
    print "A $i\n"; 
    sleep 60; 
    } 
} 

sub B { 
    for my $i (1 .. 20) { 
    print "B $i\n"; 
    sleep 60; 
    } 
} 

sub C { 
    for my $i (1 .. 3) { 
    print "C $i\n"; 
    sleep 60; 
    } 
} 
+0

因此,基本上你的例子中的每個線程都是從主線程開始的子線程,並且將是獨立的,並且具有不重疊或影響他人的睡眠持續時間。 – Nik

3

裏面的子程序記錄的時間,當它最後一次運行,然後等待,如果有必要在下次執行:

use feature 'state'; 

my $sleep_duration = 60; # seconds 

sub foo { 
    state $last_execution = 0; 
    my $remaining = $last_execution + $sleep_duration - time; 
    sleep $remaining if $remaining > 0; 
    $last_execution = time; 

    ...; # normal processing for this sub 
} 
0

這兩個答案是好的,但一種中間方式將是:(被盜由阿蒙答案)

use feature 'state'; 

my $sleep_duration = 60; # seconds 

sub foo { 
    state $last_execution = 0; 
    my $remaining = $last_execution + $sleep_duration - time; 
    if ($remaining > 0) 
    { 
     return "Waiting"; # Make sure main checks for this to know whether the sub ran. 
    } 

    ...; # normal processing for this sub 
} 

這將允許您運行,而這個等待下一子,而不需要一個以上的線程。但是,當然,這意味着這個分會只有在另外兩個人有機會之後纔會運行。這意味着您混淆了訂單並根據潛在客戶需要60秒以上的時間直到下一個電話。

+0

好吧有道理任何使用線程的警告以外,我需要小心全局變量 – Nik

+0

@Nik不是真的。有時候它有點煩躁。但是如果你打算繼續編程,學習使用和理解多線程是非常重要的。所以我會說,在一個你知道的腳本中這樣做,而且這個問題的複雜性有限,這可能是一個很好的潛入其中的概念。這些概念在所有語言中基本相似。即使讓它像線程一樣工作,也需要花費數小時,這絕對是值得的,所以請繼續。如果你遇到了一些不能按預期工作的東西(起初可能發生什麼^^) – DeVadder

+0

同意並感謝大家 - 我會給它一個可能的好機會,讓我編寫乾淨的代碼。 – Nik

1

使用阿蒙的想法,但睡覺的邏輯之外的功能,

sub get_sleeper { 

    my ($sleep_duration) = @_; 

    my $last_execution = 0; 
    return sub { 
    my $remaining = $last_execution + $sleep_duration - time(); 
    sleep $remaining if $remaining >0; 
    $last_execution = time(); 
    }; 
} 

my ($sleepA, $sleepB, $sleepC) = map get_sleeper(60), 1..3; 
while (1) { 
    $sleepA->(); SubA(); 
    $sleepB->(); SubB(); 
    $sleepC->(); SubC(); 
}