リソースの幅優先探索を実行するアルゴリズムがあります。
def crawl(starting_node)
items=[starting_node]
until items.empty?
item = items.shift
kids = item.slow_network_action # takes seconds
kids.each{ |kid| items << kid }
end
end
いくつかの同時スレッドを使用してslow_network_actionを並列化したいと思います。
これを行うための合理的な方法は何ですか?
これが機能するテクニックですが、私は確かに正しいアプローチではないと感じています:
def crawl(starting_node)
mutex = Mutex.new
items = [starting_node]
4.times.map{
loop do
unless item=mutex.synchronize{ items.shift }
sleep LONGER_THAN_LONGEST_NETWORK_ACTION
break unless item=mutex.synchronize{ items.shift }
end
kids = item.slow_network_action
mutex.synchronize{
kids.each{ |kid| items << kid }
}
end
}.each(&:join)
end
アイテムがキューに追加されるのを待っている間、スレッドを実際にスリープさせ、アイテムが追加されたときにウェイクアップし、誰もが追加されていないときにすべてのスレッドを終了させるようなことをしたいと思います。
この代替コードはほとんど機能しますが、発生する可能性のある(そして発生する)デッドロック、および適切な出口戦略の完全な欠如に対して:
require 'thread'
def crawl(starting_node)
items = Queue.new
items << starting_node
4.times.map{
while item=items.shift
kids = item.slow_network_action
kids.each{ |kid| items << kid }
end
}.each(&:join)
end