我想创建一个脚本来计算多个线程中的数字。每个线程将计算2的幂,但第一个线程必须从2开始计算,第二个线程从4开始计算,第三个线程从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
答案 0 :(得分:1)
我建议你阅读“主题和流程”章节实用程序员的红宝石书。这是一个old version在线。名为“创建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
从未达到“8”因为until
条件一看到“8”就退出。
如果您想要更清晰的输出,请将其用作loopa
:
3.times do
print "#{Thread.current}: #{s}\n"
s=s**2
end
这可以让你区分3个线程。请注意,最好使用带有换行符的字符串的print
命令而不使用不带换行符的puts
,因为后者将换行符作为单独的指令打印,可能会被另一个线程中断。 / p>
答案 1 :(得分:0)
这很正常。读你写的东西。首先,您运行3个异步线程,因此输出将在各种线程输出组合中。然后你写'我是一个线程,这些是我的结果'并加入每个线程。还记得Ruby只有引用。因此,如果您将num
传递给线程然后更改它,它将在所有线程中更改。为了避免它写:
threads = (1..3).map do |i|
puts "I'm starting thread no #{i}"
Thread.new { loopa(2**i) }
end
答案 2 :(得分: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