2012-08-28 65 views
0

我寫了一個代碼,我需要使它成爲多線程。 Evething作品,但每一個循環重複4次:線程共享的Perl

use LWP::UserAgent; 
use HTTP::Cookies; 
use threads; 
use threads::shared; 

$| = 1; 

$threads = 4; 
my @groups :shared = loadf('groups.txt'); 

my @thread_list =(); 
$thread_list[$_] = threads->create(\&thread) for 0 .. $threads - 1; 
$_->join for @thread_list; 
thread(); 

sub thread 
{ 
    my $url = 'http://www.site.ru/'; 
    my $response = $web->post($url, Content => 
        ['st.redirect' => '' 
        ]); 
    foreach $i (@groups) 
    { 

     my $response = $web->get($i); 
     if(!($response->header('Location'))) 
     { 
      ---------; 
     } 
     else 
     { 
      ----------; 
     } 

    } 

} 

sub loadf { 
    open (F, "<".$_[0]) or erroropen($_[0]); 
    chomp(my @data = <F>); 
    close F; 
    return @data; 
} 

groups.txt:

http://www.odnoklassniki.ru/group/47357692739634 
http://www.odnoklassniki.ru/group/56099517562922 

我明白,我需要使用::共享線程;但我不能忍受如何使用它。


您的帖子沒有太多的上下文來解釋代碼段;請更清楚地解釋你的情況。

+0

你期望什麼行爲?你得到了什麼?你可以刪除代碼中不重要的部分來提供一個簡單的例子嗎?請參閱http://sscce.org/ – amon

回答

5

問題是,你永遠不會從@groups中刪除,所以所有的線程在@groups做所有的工作。

下面是一個解決方案。

use threads; 
use Thread::Queue 3.01 qw(); 

my $NUM_WORKERS = 4; 

sub worker { 
    my ($url) = @_; 
    ... download the page ... 
} 

my $q = Thread::Queue->new(); 
for (1..$NUM_WORKERS) { 
    async { 
     while (my $url = $q->dequeue()) { 
     worker($url); 
     } 
    }; 
} 

$q->enqueue($_) for loadf('groups.txt'); 
$q->end(); 
$_->join() for threads->list; 
+1

如果您想要進程而不是線程,只需在頂部添加'use fork'。 – ikegami

3

爲什麼你需要使它穿線?在大多數情況下,perl的使用效果會更好。

也就是說,您的代碼啓動4個線程,每個線程處理@groups中的所有內容。這聽起來不是你想要做的。如果你想讓@groups成爲一個工作隊列,可以看看Thread :: Queue(或者Parallel :: ForkManager)。