ずいぶん前にクロウラみたいなの書こうと思って飽きちゃったネタ。なるべく同じホストへのリクエストが連続しないようにするへんなQueue。
require 'monitor' require 'thread' require 'uri' class ReservedQueue include MonitorMixin def initialize super() @queue = Queue.new @bin = Hash.new {|h, k| h[k] = []; @queue.push(h[k]); h[k]} end def push(uri) synchronize do ary = @bin[key(uri)] ary.push(uri) end end def pop synchronize do begin ary = @queue.pop end while ary.empty? uri = ary.shift if ary.empty? @bin.delete(key(uri)) else @queue.push(ary) end return uri end end def key(uri) uri.host end end
同じホストへのリクエストは末尾へ並べ直す。
rq = ReservedQueue.new rq.push(URI.parse('http://www.google.com/1')) rq.push(URI.parse('http://www.druby.org/1')) rq.push(URI.parse('http://www.druby.org/2')) rq.push(URI.parse('http://www.druby.org/3')) rq.push(URI.parse('http://www.druby.org/4')) rq.push(URI.parse('http://www.google.com/2')) rq.push(URI.parse('http://www.amaazon.co.jp')) rq.push(URI.parse('http://www.druby.org/5')) rq.push(URI.parse('http://www.google.com/2')) begin while true puts rq.pop end rescue ThreadError end
コネクションを使い回すとかの理由でおなじホストへのリクエストを連続して取得したいなら、単にArrayの方を返せばよいんだろな。
def pop @queue.pop end