2012-07-21 68 views
5

我有一個程序(Perl)能夠啓動大量線程(每個線程負責基於數據處理創建圖形)。 每個線程我開始使用:如何限制perl中並行線程的最大數量

my @threads //list to store threads that have been launched 

push @threads,threads->create(\mySubName,params...); 

螺紋火了正常,但過了一段時間,我已經打開其中幾個Perl解釋器崩潰後(我假設它關係到內存?)。所以我的解決方案是限制我一次打開的線程數,我選擇了15.我想在每條創建線之前添加一個sub,以檢查是否可以在下一個線程中觸發或執行睡眠一個完成。我試圖這樣做。

sub checkThreads{ 
    my $addThread = 0; 
    until($addThread){ 
     my $totalThreads = 0; 
     foreach my $task (@threads){ 
      if($task->is_running()){$totalThreads++;} 
     } 
     if($totalThreads <= 15){ 
      print "Ok to add new thread, carry on!\n"; 
      $addthread = 1; 
     }else{ 
      print "Waiting for $totalThreads threads to fire next one...\n"; 
      sleep 2; 
     } 
    } 
} 

所以我想創建一個新的線程,每次我只想叫

&checkThreads; 

而這會照顧到創建一個延遲,而我等待一些線程來清理。 的問題是,當我將其稱爲子,那一刻我打,我檢查線路:

$task->is_running() 

程序退出,沒有任何錯誤或警告停止運行。我只想要一個計算正在運行的線程來限制它們的子。

如何成功執行此計數?

我試圖

其他的事情正在評估以下行:

scalar(threads->list()); 

但是,這給了我一個奇怪的值,就像它是一個unblessed引用我相信是這樣的:

threads=SCALAR(0x80fea8c) 
+0

順便說一句,這是(一個字串)*祝福*裁判 – ikegami 2012-07-22 01:33:27

+1

非常,非常BTW - 請記住,perl中的線程不像其他編程語言中的線程 - 它們非常耗資源,因爲每個線程都具有所有變量的COPY。在某些情況下,它們仍然很有用,但在每個需要進行並行化的情況下,分叉的工作都會更好。這與你的問題沒有直接關係,我只是想告訴你。 :) – 2012-07-22 02:04:45

+0

什麼版本的Perl?什麼版本的線程?你的線程是否分離(可能是mySubName中的自我分離)? – pilcrow 2012-07-22 03:39:45

回答

5

Thread::Semaphore提供counting semaphore限制併發:

my $sem = Thread::Semaphore->new(15); # max 15 threads 
my @threads = map { 
    # request a thread slot, waiting if none are available: 
    $sem->down; 
    threads->create(\&mySubName, @params) 
} 0..100; 
$_->join for @threads; 

而且在你的函數:

sub mySubName { 
    do_stuff(); 
    # release slot: 
    $sem->up; 
} 
+0

理查德我認爲這是工作,我在腳本中實現它,看起來確實是它控制我的最大線程,有沒有一種方法我可以窺視信號量持有的當前值?因爲我運行了它,但經過一段時間後,我的腳本只是掛在'$ sem-> down;' – gorba 2012-07-22 03:00:33

+0

我把線程數量降低到了5,並且工作正常,仍然有7個程序在有一點,不知道爲什麼。謝謝你的提示! – gorba 2012-07-22 04:11:41

+1

您可以通過取消引用對象本身來獲取信號量的貨幣值,這只是對最大值(默認值爲1)減去其計數的有益參考。因此,要獲得當前的未完成線程數,請評估'$ max - $$ sem'。 – 2012-07-22 06:10:52

0
man perlthrtut 

What Threads Are Running? 
    "threads->list()" returns a list of thread objects, one for each thread 
    that's currently running and not detached. Handy for a number of 

換句話說,找出列表中有多少項目,threads-> list()返回並且你有你的計數。

您可能想要調查Thread::Pool或其他cpan程序包以查看是否有其他人已經爲您完成了繁重工作。

+0

當我嘗試使用threads-> list()時,我得到以下結果:在@INC中找不到auto/threads/lists.al(@INC包含:C:\ Program Files文件(x86)\ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C:\ Program Files(x86)\ ActiveState Komodo 3.5 \ lib \ support \ dbgp \ perllib C:/ Perl/lib C:/ Perl/site/main3.pl第508行 – gorba 2012-07-22 02:12:17

+0

如果'threads-> list()'返回一個列表,你可以比循環更容易捕獲長度......比如'$ totalThreads = scalar(threads-> list());',你不能嗎? – 2012-07-22 02:23:00

+0

確定這是一個錯字,我有threads-> lists()而不是threads-> list(),但是現在我運行這個 my $ totalThreads; foreach my $ thr(threads-> list()){ $ totalThreads ++; } print「Threads active:」。 $ totalThreads。 「\ n」 個; 而我得到的是: 使用未初始化值的級聯的,我打印 – gorba 2012-07-22 02:23:27

1

展望文檔,

my $count = threads->list(); 

應該工作,相反,你說什麼。 這個線程版本的文檔是用什麼來說的?那麼,你可以使用下面的解決方法。

my $count =() = threads->list(); 
+0

我使用了理查德提出的信號量方法,但我試過了,它確實給出了列表中實際線程的計數,謝謝! – gorba 2012-07-22 04:00:43