2009-11-08 27 views
5

Tôi có một tác vụ tôi cần thực hiện, do_stuff(opts), sẽ mất ~ 1 giây, ngay cả khi 1 - 10 trong số chúng chạy song song. Tôi cần thu thập một loạt các kết quả cho từng hoạt động ở cuối.Luồng trong Ruby với giới hạn

Nếu tôi có 30 nội dung cần làm, làm cách nào để sử dụng luồng hiệu quả để xếp hàng hoạt động do_stuff(opts) do đó không quá 10 hoạt động đồng thời, nhưng kết quả không được cung cấp/in/etc cho đến khi tất cả (30) công việc đã được hoàn thành?

Tôi thường có ít nhất một số mã để thử và minh họa những gì tôi có ý nghĩa, nhưng với luồng tôi đang ở một chút mất mát! Cảm ơn trước

Trả lời

2

Bạn cần phải thực hiện this pattern
This question thảo luận làm thế nào mà có thể được thực hiện trong Ruby

0

Ngoài ra, hãy nhìn vào this hướng dẫn nếu bạn là người mới đến chủ đề Ruby.

+1

Liên kết của bạn dường như đã chết. Có bản sao nào đó không? – Naremy

+0

@Naremy, tôi đã sửa liên kết. Xin vui lòng upvote khi bạn có một thời điểm. – jkndrkn

+0

Tôi đã không phải là downvoter nhưng nếu tôi có thể làm cho hạnh phúc của bạn;) – Naremy

1

Nếu bạn đang thực sự sau buổi biểu diễn, bạn cũng có thể muốn xem xét jruby.
Nó sử dụng chủ đề OS thực tế và không phải là chủ đề xanh triển khai ruby ​​khác sử dụng

4

I dunno tốt như thế nào nó sẽ làm việc cho một ứng dụng phức tạp hơn, nhưng tôi tìm thấy một cái gì đó như thế này để làm việc độc đáo cho một kịch bản đơn giản với luồng macruby.

thread_limit = 4 

threads = [] 
things_to_process.each do |thing| 
    until threads.map { |t| t.status }.count("run") < thread_limit do sleep 5 end 
    threads << Thread.new { the_task(thing) } 
end 
output = threads.map { |t| t.value } 

vòng lặp chờ đợi cho đến khi có ít hơn số lượng quy định của chuỗi đã tạo trước khi cho phép thực hiện chuỗi chính tiếp tục bắt đầu chuỗi tiếp theo.

biến đầu ra sẽ được chỉ định một mảng giá trị được trả về bởi_task với một thứ tự tương ứng với mảng đầu vào things_to_process. Chủ đề chính sẽ chặn cho đến khi mọi chuỗi được tạo trả về một giá trị.

+1

Tôi đã may mắn hơn bằng cách sử dụng thread.alive? thay vì trạng thái: 'threads.map {| t | t.alive?}. count (true) ' – theglauber

1

Giải pháp này thu thập kết quả trong mảng kết quả $. Nó cho phép tạo luồng 'thread_limit', sau đó đợi chúng hoàn thành trước khi tạo thêm nữa.

$results = [] 

    def do_stuff(opts={}) 
    'done' 
    end 

    def thread_wait(threads) 
    threads.each{|t| t.join} 
    threads.each {|t| $results << t } 
    threads.delete_if {|t| t.status == false} 
    threads.delete_if {|t| t.status.nil? } 
    end 

    opts = {} 
    thread_limit = 20 
    threads = [] 
    records.each do |r| 
    thread_wait(threads) while threads.length >= thread_limit 
    t = Thread.new { do_stuff(opts) } 
    t.abort_on_exception = true 
    threads << t 
    end 
    # Ensure remaining threads complete 
    threads.each{|t| t.join} 
0

tôi sử dụng paralsparalsmap:

def parals(objects, n: 50) 
    objects.shuffle.each_slice(n).map do |g| 
    print '{' 
    threads = [] 
    g.map { |i| threads << Thread.new(i) { |i| yield(i) } } 
    threads.each(&:join) 
    print '}' 
    end 
end 

def paralsmap(objects, n: 50) 
    res = [] 

    objects.each_slice(n).map do |g| 
    print '{' 
    threads = [] 
    g.map { |i| threads << Thread.new(i, res) { |i| res << yield(i) } } 
    threads.each(&:join) 
    print '}' 
    end 

    res 
end 

ví dụ .:

parals((0..100).to_a) { |i| puts i } 
urls = parals((0..100).to_a) { |i| "https://google.com/?q=#{i}" } 

Bạn có thể sử dụng tham số n để hạn chế số lượng bài.

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