5

テキストファイルを解析し、データを並行してダウンロードするプログラムを作成しました。9スレッド以下でダウンロードメソッドを実行する場合、プログラムにエラーはありません。ただし、メソッドを10以上のスレッドで実行すると、プログラムは「 `initialize':getaddrinfo:Name or service notknown(SocketError)」エラーをスローします。いくつかのアルゴリズムを並行して実行しようとしましたが、同じ問題が発生します。「名前またはサービスが不明」エラーが発生したときに「open」メソッド(open-uri)に渡されたURLをブラウザに入れ、このURLが有効であり、正しいデータを受信したことを確認しました。これが部分的なコードです。

jobs = []
aps = []
....
#jobs are pushed into jobs[]
....
max_thread = 15
loop do
  ary_threads = []
  max_thread.times do |i|
    break if jobs.size == 0
    job =  jobs.pop
    ary_threads << Thread.start {
      begin
        request(job[0],job[1]).each do |ap| #in "request" method, open(url)are called
            aps.push(ap)
        end
      end
    }
 end
 ary_threads.each { |th| th.join }
 break if jobs.size == 0
end

エラーは

/usr/lib/ruby/1.9.1/net/http.rb:762:in `initialize': getaddrinfo: Name or service not known (SocketError)
from /usr/lib/ruby/1.9.1/net/http.rb:762:in `open'
from /usr/lib/ruby/1.9.1/net/http.rb:762:in `block in connect'
from /usr/lib/ruby/1.9.1/timeout.rb:54:in `timeout'
from /usr/lib/ruby/1.9.1/timeout.rb:99:in `timeout'
from /usr/lib/ruby/1.9.1/net/http.rb:762:in `connect'
from /usr/lib/ruby/1.9.1/net/http.rb:755:in `do_start'
from /usr/lib/ruby/1.9.1/net/http.rb:744:in `start'
from /usr/lib/ruby/1.9.1/open-uri.rb:306:in `open_http'
from /usr/lib/ruby/1.9.1/open-uri.rb:775:in `buffer_open'
from /usr/lib/ruby/1.9.1/open-uri.rb:203:in `block in open_loop'
from /usr/lib/ruby/1.9.1/open-uri.rb:201:in `catch'
from /usr/lib/ruby/1.9.1/open-uri.rb:201:in `open_loop'
from /usr/lib/ruby/1.9.1/open-uri.rb:146:in `open_uri'
from /var/lib/gems/1.9.1/gems/open-uri-cached-0.0.5/lib/open-uri/cached.rb:10:in `open_uri'
from /usr/lib/ruby/1.9.1/open-uri.rb:677:in `open'
from /usr/lib/ruby/1.9.1/open-uri.rb:33:in `open'
from Test1.rb:42:in `request'
from Test1.rb:77:in `block (3 levels) in <main>'

なぜこれが起こるのですか?誰かが同様の問題に遭遇しましたか?私を助けてください!

最初の質問から3時間後、一時的な解決策を見つけました。「リクエスト」メソッドの「オープン」メソッドを「開始〜レスキュー〜再試行〜終了」で挟んだ場合、2回目の「オープン」が呼び出されてもエラーは発生しません。コードは次のとおりです。

begin
    response = open(url)
rescue Exception
    puts url
    puts "retrying"
    retry
end

例外をキャッチしてURLと「再試行」を表示した後、URLと「再試行」は表示されず、プログラムは正しく動作します:)しかし、それでもこの問題の原因を見つけることができません。

4

1 に答える 1

3

スレッド間の競合状態が原因かもしれないと思います。アトミックに操作してみてください。ミューテックスロックをかけます。

    @mutex = Mutex.new

    @mutex.syncronize do
      ...

      ary_threads << Thread.start {
       begin
        request(job[0],job[1]).each do |ap| #in "request" method, open(url)are called
          aps.push(ap)
        end
        end
      }

      ...
    end
于 2013-07-26T09:25:24.680 に答える