2016-04-07 134 views
0

我想實現一個簡單的超時類來處理不同請求的超時。相同代碼的兩個版本沒有給出相同的結果

這是第一個版本:

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 

Screenshot attached

這究竟是爲什麼?

如何使用數組實現此功能?

是否有實現相同功能的更好的辦法?

回答

0

在您通過使用Thread.new創建線程的循環中,變量imain線程(線程正在創建中)和創建的線程之間共享。因此,handleTimeout看到的i的值不一致,您會得到不同的結果。

你可以在你的方法添加調試語句驗證此:

#... 
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描述。

+0

我會用這樣的處理超時的請求到服務器。有沒有更好的方法來做到這一點? –

+0

@ B.Nabi這些是什麼樣的要求? HTTP? –

+0

是HTTP請求。 –

相關問題