2010-03-16 12 views
8

मैं एक पर्ल स्क्रिप्ट है कि 2 सूत्र, प्रत्येक प्रोसेसर के लिए एक शुरूआत की है। मैं एक धागा समाप्त हो जाती है, तो एक नया एक पैदा की है यह अंत करने के लिए एक धागा के लिए इंतजार करना, की जरूरत है। ऐसा नहीं है कि विधि ब्लॉक कार्यक्रम के बाकी में शामिल होने, इसलिए दूसरा धागा सब कुछ पहले धागा है किया जाता है जो एक तरह से अपने उद्देश्य धरा जब तक समाप्त नहीं हो सकता है।पर्ल में, मैं धागे समानांतर में समाप्त करने के लिए के लिए कैसे इंतजार कर सकते हैं?

मैंने is_joinable विधि की कोशिश की लेकिन ऐसा लगता है कि ऐसा नहीं लगता है।

यहाँ है मेरी कोड के कुछ:

use threads; 
use threads::shared; 

@file_list = @ARGV;  #Our file list 
$nofiles = $#file_list + 1; #Real number of files 
$currfile = 1;  #Current number of file to process 

my %MSG : shared;    #shared hash 

$thr0 = threads->new(\&process, shift(@file_list)); 
$currfile++; 
$thr1 = threads->new(\&process, shift(@file_list)); 
$currfile++; 

while(1){ 
if ($thr0->is_joinable()) { 
    $thr0->join; 
     #check if there are files left to process 
    if($currfile <= $nofiles){ 
    $thr0 = threads->new(\&process, shift(@file_list)); 
    $currfile++; 
    } 
} 

if ($thr1->is_joinable()) { 
    $thr1->join; 
     #check if there are files left to process 
    if($currfile <= $nofiles){ 
    $thr1 = threads->new(\&process, shift(@file_list)); 
    $currfile++; 
    } 
} 
} 

sub process{ 
     print "Opening $currfile of $nofiles\n"; 
     #do some stuff 
     if(some condition){ 
       lock(%MSG); 
       #write stuff to hash 
     } 
     print "Closing $currfile of $nofiles\n"; 
} 

इस के उत्पादन में है:

Opening 1 of 4 
Opening 2 of 4 
Closing 1 of 4 
Opening 3 of 4 
Closing 3 of 4 
Opening 4 of 4 
Closing 2 of 4 
Closing 4 of 4 

उत्तर

5

मैं तुम्हें कोड है कि धागे में सूची से अगले फ़ाइल खींचती बढ़ने की जरूरत है लगता है खुद को।

तो प्रत्येक धागा सिर्फ एक फ़ाइल को संसाधित नहीं करेगा, लेकिन सूची खाली होने तक प्रक्रिया जारी रखेगी।

इस तरह, आप हर समय नए धागे बनाने के ऊपरी हिस्से को भी बचाते हैं।

आपका मुख्य धागा तब दोनों में शामिल होगा।

बेशक, इस सूची में सिंक्रनाइज़ेशन की आवश्यकता है (ताकि वे एक ही डेटा खींच न सकें)। वैकल्पिक रूप से, आप दो (प्रत्येक थ्रेड के लिए एक) में सूची विभाजित किया जा सकता, लेकिन यह एक अशुभ वितरण हो सकती है।

(पी एस: नहीं पर्ल भगवान, बस एक विनम्र भिक्षु)

+0

आज आप मेरे भगवान हैं;) अच्छा समाधान .. एक और बात: ताले को सूची में डालने के लिए अब मैं यह करता हूं: अगर (1 == 1) {लॉक (@file_list); $ फ़ाइल = शिफ्ट (@file_list); } मुझे इसकी आवश्यकता है अगर यह कार्य चलाने से पहले अंत में अनलॉक हो जाए। हालांकि यह एक सुंदर नोब-हैक जैसा लगता है :) कोई बेहतर तरीका? – Pmarcoen

9

पहले, कोड पर ही कुछ टिप्पणी नहीं। हर स्क्रिप्ट की शुरुआत में

use strict; 
use warnings; 

: आप सुनिश्चित करें कि आपके की जरूरत है। दूसरा: के रूप में अदिश संदर्भ में एक सरणी सरणी में तत्वों की संख्या का आकलन करती

@file_list = @ARGV;  #Our file list 
$nofiles = $#file_list + 1; #Real number of files 

अनावश्यक है। यही कारण है:

$nofiles = @ARGV; 

सही ढंग से आप फ़ाइलों की संख्या @ARGV में परवाह किए बिना $[ के मूल्य का देना होगा।

अंत में, स्क्रिप्ट धागे शुरू करने से पहले बहुत फ़ाइलों की सूची विभाजन द्वारा सरल बनाया जा सकता है:

use strict; use warnings; 

use threads; 
use threads::shared; 

my @threads = (
    threads->new(\&process, @ARGV[0 .. @ARGV/2]), 
    threads->new(\&process, @ARGV[@ARGV/2 + 1 .. @ARGV - 1]), 
); 

$_->join for @threads; 

sub process { 
    my @files = @_; 
    warn "called with @files\n"; 
    for my $file (@files) { 
     warn "opening '$file'\n"; 
     sleep rand 3; 
     warn "closing '$file'\n"; 
    } 
} 

आउटपुट:

C:\Temp> thr 1 2 3 4 5 
called with 1 2 3 
opening '1' 
called with 4 5 
opening '4' 
closing '4' 
opening '5' 
closing '1' 
opening '2' 
closing '5' 
closing '2' 
opening '3' 
closing '3'

वैकल्पिक रूप से, आप धागे पर चलते दे सकते हैं अगले काम के रूप में वे किया जाता है:

use strict; use warnings; 

use threads; 
use threads::shared; 

my $current :shared; 
$current = 0; 

my @threads = map { threads->new(\&process, $_) } 1 .. 2; 
$_->join for @threads; 

sub process { 
    my ($thr) = @_; 
    warn "thread $thr stared\n"; 

    while (1) { 
     my $file; 
     { 
      lock $current; 
      return unless $current < @ARGV; 
      $file = $ARGV[$current]; 
      ++ $current; 
     } 
     warn "$thr: opening '$file'\n"; 
     sleep rand 5; 
     warn "$thr: closing '$file'\n"; 
    } 
} 

आउटपुट:

C:\Temp> thr 1 2 3 4 5 
thread 1 stared 
1: opening '1' 
1: closing '1' 
1: opening '2' 
thread 2 stared 
2: opening '3' 
2: closing '3' 
2: opening '4' 
1: closing '2' 
1: opening '5' 
1: closing '5' 
2: closing '4'
+0

आपकी टिप्पणियों के लिए धन्यवाद, आपकी टिप्पणियों को पढ़ने से पहले पहले से ही थिलो के समाधान को लागू किया गया है, इसलिए उसका जवाब चुना लेकिन मैं निश्चित रूप से आपके सुझावों का उपयोग करूंगा! – Pmarcoen

+1

पहले से काम करने वाले सेट को विभाजित करने से दुर्भाग्यपूर्ण वितरण हो सकता है। – Thilo

संबंधित मुद्दे