2011-09-26 6 views
9

Мне интересно, как я могу открыть несколько параллельных соединений с помощью open-uri? Я ДУМАЮ, что мне нужно использовать потоки или волокна, но я не уверен.Как обрабатывать элементы в массиве в параллельном режиме с помощью Ruby (и open-uri)

Пример кода:

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 

ответ

10

Там же камень называется Parallel, который похож на персик, но активно обновляется.

-1

Существует драгоценный камень называется peach (https://rubygems.org/gems/peach), который позволяет сделать это:

require "peach" 

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

Драгоценный камень - только жрубы –

7

Я надеюсь, что это дает вам представление:

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} 

Возможно создание способа Array как:

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 

Использование:

arr = [1,2,3] 

arr.extend(MultithreadedEach) 

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

Простой метод, использующий Темы:

threads = [] 

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

threads.each(&:join)