我正在尝试实现一个处理不同请求超时的简单超时类。
这是第一个版本:
class MyTimer
def handleTimeout mHash, k
while mHash[k] > 0 do
mHash[k] -=1
sleep 1
puts "#{k} : #{mHash[k]}"
end
end
end
MAX = 3
timeout = Hash.new
timeout[1] = 41
timeout[2] = 5
timeout[3] = 14
t1 = MyTimer.new
t2 = MyTimer.new
t3 = MyTimer.new
first = Thread.new do
t1.handleTimeout(timeout,1)
end
second = Thread.new do
t2.handleTimeout(timeout,2)
end
third = Thread.new do
t3.handleTimeout(timeout,3)
end
first.join
second.join
third.join
这似乎工作正常。所有超时都相互独立。 Screenshot attached
然而,代码的第二个版本会产生不同的结果:
class MyTimer
def handleTimeout mHash, k
while mHash[k] > 0 do
mHash[k] -=1
sleep 1
puts "#{k} : #{mHash[k]}"
end
end
end
MAX = 3
timeout = Hash.new
timers = Array.new(MAX+1)
threads = Array.new(MAX+1)
for i in 0..MAX do
timeout[i] = rand(40)
# To see timeout value
puts "#{i} : #{timeout[i]}"
end
sleep 1
for i in 0..MAX do
timers[i] = MyTimer.new
threads[i] = Thread.new do
timers[i].handleTimeout( timeout, i)
end
end
for i in 0..MAX do
threads[i].join
end
为什么会这样?
如何使用数组实现此功能?
有没有更好的方法来实现相同的功能?
答案 0 :(得分:0)
在使用Thread.new
创建线程的循环中,变量i
在main
线程(创建线程的位置)和创建的线程之间共享。因此,i
看到的handleTimeout
值并不一致,您会得到不同的结果。
您可以通过在方法中添加调试语句来验证这一点:
#...
def handleTimeout mHash, k
puts "Handle timeout called for #{mHash} and #{k}"
#...
end
#...
要解决此问题,您需要使用以下代码。这里将参数传递给Thread.new
,然后使用块变量进行访问。
for i in 0..MAX do
timers[i] = MyTimer.new
threads[i] = Thread.new(timeout, i) do |a, b|
timers[i].handleTimeout(a, b)
end
end
When do you need to pass arguments to Thread.new
?和此article中介绍了有关此问题的更多信息。