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