-2

複数のスレッドで数値を計算するスクリプトを作成したいと思います。各スレッドは2の累乗を計算しますが、最初のスレッドは2から計算を開始し、2番目は4から、3番目は8から計算を開始し、間にテキストを出力する必要があります。

例:

Im a thread and these are my results
2
4
8
Im a thread and these are my results
4
8
16
Im a thread and these are my results
8
16
32

私の失敗コード:

def loopa(s)
    3.times do
        puts s
        s=s**2
    end
end
threads=[]
num=2
until num == 8 do
    threads << Thread.new{ loopa(num) }
    num=num**2
end
threads.each { |x| puts "Im a thread and these are my results" ; x.join }

私の失敗の結果:

Im a thread and these are my results
8
64
4096
8
64
4096
8
64
4096
Im a thread and these are my results
Im a thread and these are my results
4

3 に答える 3

1

「スレッドとプロセス」の章「実用的なプログラマーのルビーの本」を読むことをお勧めします。これがオンラインの古いバージョンです。「 Rubyスレッドの作成」というセクションは、特にあなたの質問に関連しています。

Thread.newこの問題を解決するには、行を次のように変更する必要があります。

threads << Thread.new(num){|n| loopa(n) }

スレッド間で共有されているため、バージョンが機能せずnum、別のスレッドによって変更される可能性があります。ブロックを介して変数を渡すことにより、ブロック変数は共有されなくなります。

より詳しい情報

また、あなたの数学に誤りがあります。出力値は次のようになります。

Thread 1: 2 4 16
Thread 2: 4 16 256
Thread 3: 6 36 1296

until「8」が表示されるとすぐに条件が終了するため、「8」に到達することはありません。

より明確な出力が必要な場合は、これをloopa:の本文として使用してください。

3.times do
    print "#{Thread.current}: #{s}\n"
    s=s**2
end

これにより、3つのスレッドを区別できます。print改行なしで使用するよりも、改行で終了する文字列を使用する方が良いことに注意してくださいputs。後者は、改行を別の命令として出力し、別のスレッドによって中断される可能性があるためです。

于 2012-09-13T17:50:25.397 に答える
0

正常です。あなたが書いたものを読んでください。まず、非同期の3つのスレッドを実行するため、出力はスレッド出力のさまざまな組み合わせになります。次に、「Im a thread and these are my results」と記述し、各スレッドを結合します。また、Rubyには参照しかないことを忘れないでください。したがって、スレッドに渡しnumてから変更すると、すべてのスレッドで変更されます。それを避けるために書く:

threads = (1..3).map do |i|
  puts "I'm starting thread no #{i}"
  Thread.new { loopa(2**i) }
end
于 2012-09-13T17:53:04.523 に答える
0

数学的に正しいバージョンを投稿する必要があると感じています。

def loopa(s)
  3.times do
      print "#{Thread.current}: #{s}\n"
      s *= 2
  end
end

threads=[]
num=2
while num <= 8 do
    threads << Thread.new(num){|n| loopa(n) }
    num *= 2
end

threads.each { |x| print "Im a thread and these are my results\n" ; x.join }

ボーナス1:スレッドレスソリューション(ナイーブ)

power = 1
workers = 3
iterations = 3

(power ... power + workers).each do |pow|
  worker_pow = 2 ** pow
  puts "I'm a worker and these are my results"
  iterations.times do |inum|
    puts worker_pow
    worker_pow *= 2
  end
end

ボーナス2:スレッドレスソリューション(キャッシュ)

power = 1
workers = 3
iterations = 3

cache_size = workers + iterations - 1
# generate all the values upfront
cache = []
(power ... power+cache_size).each do |i|
  cache << 2**i
end

workers.times do |wnum|
  puts "I'm a worker and these are my results"
  # use a sliding-window to grab the part of the cache we want
  puts cache[wnum,3]
end
于 2012-09-13T18:22:52.833 に答える