2012-01-08 7 views
7

私はURLの配列を持っていて、それぞれを開き、特定のタグをフェッチすることはできません。
しかし、これを並行して実行したいと思います。ここでルビーでの並列HTTPリクエスト

は、私が何をしたいのための擬似コードです:

 
urls = [...] 
tags = [] 
urls.each do |url| 
    fetch_tag_asynchronously(url) do |tag| 
    tags << tag 
    end 
end 
wait_for_all_requests_to_finish() 

これは素晴らしいだろう素敵で安全な方法で行うことができれば。
スレッドを使用することはできますが、配列はルビーのスレッドセーフではありません。あなたはMutexを使用して、スレッドの安全性を達成することができます

答えて

25

require 'thread' # for Mutex 

urls = %w(
    http://test1.example.org/ 
    http://test2.example.org/ 
    ... 
) 

threads = [] 
tags = [] 
tags_mutex = Mutex.new 

urls.each do |url| 
    threads << Thread.new(url, tags) do |url, tags| 
    tag = fetch_tag(url) 
    tags_mutex.synchronize { tags << tag } 
    end 
end 

threads.each(&:join) 

をただし、すべてのURLのための新しいスレッドを使用して逆効果かもしれないので、このようなスレッドの数を制限することは、よりパフォーマンスの高いかもしれません:

+0

ハハ、これは私が書いた全く同じ解決策でした! :) –

+0

仕事の大部分がIOの場合、コアの数は本当に重要ではありませんか? – ben

+0

@ben:そうです。それでも、同時にスレッドとオープンな接続が多すぎると、生産性が低下する可能性があります。 FirefoxはHTTPパイプライニングでデフォルトの8接続を使用しているので、これを推奨値(5ではなく)として使用します。 –

7

Typhoeus/Hydra宝石の組み合わせは、これを非常に簡単に行うように設計されています。それは非常に便利で強力です。

+1

スレッドセーフではありません – Imnl

関連する問題