为什么结果不是1到10,而只是10s?
require 'thread'
def run(i)
puts i
end
while true
for i in 0..10
Thread.new{ run(i)}
end
sleep(100)
end
结果:
10
10
10
10
10
10
10
10
10
10
10
为什么要循环?我正在循环运行,因为后来我想一直遍历数据库表并回显从数据库中检索到的任何记录。
答案 0 :(得分:8)
传递给Thread.new
的块实际上可能在将来某个时间点开始,到那时i
的值可能已经改变。在您的情况下,在所有线程实际运行之前,它们都增加到10
。
要解决此问题,除了块之外,还要使用接受参数的Thread.new
形式:
require 'thread'
def run(i)
puts i
end
while true
for i in 0..10
Thread.new(i) { |j| run(j) }
end
sleep(100)
end
这会在调用j
时将块变量i
设置为new
的值。
答案 1 :(得分:2)
@DavidGrayson是对的。
您可以在此处看到for loop
中的副作用。在您的情况下,i
变量范围是您的整个文件。虽然您希望for loop
中只有一个区块作为范围。实际上这在惯用Ruby中是错误的方法。 Ruby为这项工作提供了迭代器。
(1..10).each do |i|
Thread.new{ run(i)}
end
在这种情况下,变量i
的范围将在块范围内被隔离,对于每次迭代,您将获得新的本地(对于此块)变量i
。
答案 2 :(得分:1)
问题是你创建了11个线程,它们都试图访问由程序主线程定义的同一个变量i
。避免这种情况的一个技巧是在方法中调用Thread.new
;那么线程有权访问的变量i
就是传递给方法的特定i
,并且不与其他线程共享。这利用了closure。
require 'thread'
def run(i)
puts i
end
def start_thread(i)
Thread.new { run i }
end
for i in 0..10
start_thread i
sleep 0.1
end
结果:
0
1
2
3
4
5
6
7
8
9
10
(我添加了sleep
只是为了保证线程以数字顺序运行,所以我们可以得到整齐的输出,但你可以把它拿出来并且仍然有一个有效的程序,其中每个线程都获得正确的参数。)