2012-07-21 28 views
5

Tôi có một chương trình (Perl) khởi động một số lượng lớn các luồng (mỗi người chịu trách nhiệm tạo đồ họa dựa trên xử lý dữ liệu). Mỗi thread Tôi bắt đầu sử dụng:Làm thế nào để giới hạn số lượng tối đa của các chủ đề song song trong perl

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

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

Các bài bắn ra một cách chính xác nhưng sau một thời gian, sau khi tôi đã mở một vài trong số họ Perl tai nạn thông dịch viên (tôi giả sử nó có liên quan đến bộ nhớ?). Vì vậy, giải pháp của tôi là giới hạn số lượng chủ đề tôi mở cùng một lúc, tôi đã chọn 15. Và tôi muốn thêm một phụ trước mỗi dòng tạo để kiểm tra xem có ổn không nếu bạn muốn tắt chuỗi tiếp theo hoặc thực hiện chế độ ngủ trong khi chờ cho một kết thúc. Đây là cách tôi đã cố gắng để làm điều đó.

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; 
     } 
    } 
} 

Vì vậy, mỗi khi tôi muốn tạo một chủ đề mới tôi sẽ chỉ gọi

&checkThreads; 

Và đó sẽ chăm sóc để tạo ra một sự chậm trễ trong khi tôi chờ đợi đối với một số chủ đề để làm sạch. Vấn đề là khi tôi gọi sub rằng, thời điểm này tôi nhấn dòng nơi tôi kiểm tra:

$task->is_running() 

Các thoát khỏi chương trình và ngừng chạy mà không có bất kỳ lỗi hoặc cảnh báo. Tôi chỉ muốn một phụ mà đếm các chủ đề đang chạy để hạn chế chúng.

Làm cách nào để tôi có thể thực hiện thành công tính năng này?

điều

khác Tôi đã thử đang đánh giá các dòng sau:

scalar(threads->list()); 

Nhưng điều đó mang lại cho tôi một giá trị kỳ lạ, giống như nó là một tài liệu tham khảo không được ban phước Tôi tin rằng trông giống như:

threads=SCALAR(0x80fea8c) 
+0

btw, đó là (stringification a) * may mắn * ref – ikegami

+1

rất, rất BTW - Hãy nhớ rằng các chủ đề trong perl không giống như các chủ đề trong các ngôn ngữ lập trình khác - chúng rất thiếu tài nguyên, vì mỗi luồng có COPY của tất cả các biến.Chúng vẫn hữu ích trong một số trường hợp, nhưng trong mọi trường hợp tôi phải làm paralellization, forking hoạt động tốt hơn nhiều. Nó không liên quan trực tiếp đến câu hỏi của bạn, tôi chỉ muốn nói với bạn điều đó. :) –

+0

Phiên bản nào của Perl? Phiên bản chủ đề nào? Và các chủ đề của bạn có tách rời (có lẽ tự tách trong mySubName) không? – pilcrow

Trả lời

5

Thread::Semaphore cung cấp một counting semaphore để hạn chế đồng thời:

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; 

Và trong chức năng của bạn:

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

Richard Tôi nghĩ rằng điều này là làm việc, tôi thực hiện nó trong kịch bản và trông giống như thực sự nó là kiểm soát chủ đề tối đa của tôi, là có một cách tôi có thể nhìn vào giá trị hiện tại mà semaphore giữ? Bởi vì tôi chạy nó nhưng sau khi đi vào nó một lúc, kịch bản của tôi chỉ bị treo ở một '$ sem-> down; ' – gorba

+0

Tôi giảm số lượng chủ đề xuống 5 và nó hoạt động tốt, vẫn với 7 trông giống như các quầy hàng chương trình tại một số điểm, không chắc chắn lý do tại sao. Cảm ơn vì tiền hỗ trợ! – gorba

+1

Bạn có thể nhận được giá trị tiền tệ của semaphore bằng cách dereferencing chính đối tượng, mà chỉ là một tham chiếu may mắn cho giá trị tối đa (mặc định là 1) trừ đi số lượng của nó. Vì vậy, để có được số lượng hiện tại của chủ đề nổi bật, đánh giá '$ max - $$ sem'. –

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 

Nói cách khác, hãy tìm xem có bao nhiêu mục nằm trong danh sách mà luồng-> list() trả về và bạn có số đếm.

Bạn có thể muốn điều tra Thread::Pool hoặc các gói cpan khác để xem liệu có ai đó đã thực hiện việc nâng hạng nặng cho bạn hay không.

+0

Khi tôi cố gắng sử dụng thread-> list(), tôi nhận được kết quả sau: Không thể xác định vị trí auto/threads/lists.al trong @INC (@INC chứa: 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/lib.) tại C: \ path \ main3.pl line 508 – gorba

+0

Nếu 'threads-> list()' trả về một danh sách, bạn có thể nắm bắt được chiều dài dễ dàng hơn với một vòng lặp ... như '$ totalThreads = scalar (threads-> list());', phải không? –

+0

ok nó là một lỗi đánh máy, tôi đã có chủ đề-> danh sách() thay vì thread-> list(), nhưng bây giờ tôi chạy này $ totalThreads của tôi; foreach $ thr của tôi (threads-> list()) { $ totalThreads ++; } in "Chủ đề đang hoạt động:". $ totalThreads. "\ n"; Và những gì tôi nhận được là: Sử dụng giá trị chưa được khởi tạo trong nối (.) Cho dòng mà tôi in – gorba

1

Nhìn các tài liệu,

my $count = threads->list(); 

nên làm việc, trái với những gì bạn nói. Tài liệu cho phiên bản của chủ đề bạn đang sử dụng nói gì? Vâng, bạn có thể sử dụng sau đây như một cách giải quyết.

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

Tôi đã sử dụng cách tiếp cận semaphore mà Richard đề xuất, nhưng tôi đã thử điều này và nó đưa ra số lượng các chủ đề thực tế trong danh sách, cảm ơn! – gorba

Các vấn đề liên quan