2011-09-26 5 views
9

Zastanawiam się, w jaki sposób mogę przejść do otwierania wielu równoczesnych połączeń za pomocą open-uri? Myślę, że muszę używać wątków lub włókien, ale nie jestem pewien.Jak przetwarzać elementy w tablicy równolegle za pomocą Ruby (i open-uri)

Przykładowy kod:

def get_doc(url) 
    begin 
    Nokogiri::HTML(open(url).read) 
    rescue Exception => ex 
    puts "Failed at #{Time.now}" 
    puts "Error: #{ex}" 
    end 
end 

array_of_urls_to_process = [......] 

# How can I iterate over items in the array in parallel (instead of one at a time?) 
array_of_urls_to_process.each do |url| 
    x = get_doc(url) 
    do_something(x) 
end 

Odpowiedz

10

Istnieje również klejnot zwany Parallel który jest podobny do Peach, ale jest aktywnie aktualizowane.

-1

Jest to klejnot zwany peach (https://rubygems.org/gems/peach), która pozwala to zrobić:

require "peach" 

array_of_urls_to_process.peach do |url| 
    do_something(get_doc(url)) 
end 
+0

Klejnot jest tylko jubilerski –

7

Mam nadzieję, że to daje wyobrażenie:

def do_something(url, secs) 
    sleep secs #just to see a difference 
    puts "Done with: #{url}" 
end 

threads = [] 
urls_ary = ['url1', 'url2', 'url3'] 

urls_ary.each_with_index do |url, i| 
    threads << Thread.new{ do_something(url, i+1) } 
    puts "Out of loop #{i+1}" 
end 
threads.each{|t| t.join} 

Może tworząc metodę Array jak:

class Array 
    def thread_each(&block) 
     inject([]){|threads,e| threads << Thread.new{yield(e)}}.each{|t| t.join} 
    end 
end 

[1, 2, 3].thread_each do |i| 
    sleep 4-i #so first one ends later 
    puts "Done with #{i}" 
end 
2
module MultithreadedEach 
    def multithreaded_each 
    each_with_object([]) do |item, threads| 
     threads << Thread.new { yield item } 
    end.each { |thread| thread.join } 
    self 
    end 
end 

Zastosowanie:

arr = [1,2,3] 

arr.extend(MultithreadedEach) 

arr.multithreaded_each do |n| 
    puts n # Each block runs in it's own thread 
end 
0

Prosty sposób korzystania wątki:

threads = [] 

[1, 2, 3].each do |i| 
    threads << Thread.new { puts i } 
end 

threads.each(&:join) 
Powiązane problemy