1

毎秒リモート サービスを呼び出す機能を実行したいと考えています。これを行うには、次のようなものがあります。

stop = false
text = ""

while stop == false
  r = RestClient.post 'http://example.com'
  text += r.to_str
  sleep 1
  # after a treatment, the value of stop will set to true
end

問題は、http 要求が完了するまでプログラムがブロックされることであり、私はそれを望んでいません。このコードをサブプロセスに入れることはできますが、結果を呼び出し順に保持したいと考えています。たとえば、次のリクエストを行うことができます。

 time | anwser
--------------
  10  | Happy
  100 | New
  10  | Year

2 番目の要求は 3 番目の要求よりも長いため、スレッドを使用すると、2 番目の前に 3 番目の結果が得られ、変数の値はtextand HappyYearNewI want になりHappyNewYearます。

複数のプロセスを持ち、元の順序を維持する方法はありますか? これは非常に小さなプログラムです。可能であれば、redis のようなサーバーをインストールする必要はありません。

4

2 に答える 2

1

ハッシュの使用

ruby-1.9以降、ハッシュキーの順序が保証されています。ここでの簡単な解決策は、リクエストをハッシュに入れて、キーでハッシュ要素にアクセスする結果を保存することにより、それを利用することです:

requests = {
  foo: [ 'a', 1 ],
  bar: [ 'b', 5 ],
  foobar: [ 'c', 2 ]
}

requests.each do |name, config|
  Thread.new( name, config ) do |name, config|
    sleep config[1]
    requests[ name ] = config[0]
  end
end

sleep 6

requests.each do |name, result|
  puts "#{name} : #{result}"
end

プロデュース:

foo : a
bar : b
foobar : c

したがって、提供されたコードと一致させるには:

stop, i, text, requests = false, 0, '', {}

until stop
  i += 1
  requests[ i ] = nil

  Thread.new( i ) do |key|
    r = RestClient.post 'http://example.com'
    requests[ i ] = r.to_str
    sleep 1
    # after a treatment, the value of stop will set to true
  end
end

# you will have to join threads, here
text = requests.values.join

配列の使用

最後の例が適切であれば、配列を使用して単純化することもできます。もちろん、配列の順序も保証されており、ルビ配列の動的サイズの性質を利用できます。

a = []
a[5] = 1
p a
=> [nil, nil, nil, nil, nil, 1]

したがって、前の例は次のように書き換えることができます。

stop, i, text, requests = false, 0, '', []

until stop
  i += 1

  Thread.new( i ) do |key|
    r = RestClient.post 'http://example.com'
    requests[ i ] = r.to_str
    sleep 1
    # after a treatment, the value of stop will set to true
  end
end

# you will have to join threads, here
text = requests.join
于 2013-11-06T18:51:39.003 に答える