2012-08-28 68 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)。