【问题标题】:Ruby threads calling the same function with different argumentsRuby 线程使用不同的参数调用相同的函数
【发布时间】:2015-11-10 08:22:14
【问题描述】:

我正在使用多个线程(例如 10 个线程)调用相同的 Ruby 函数。每个线程将不同的参数传递给函数。

例子:

def test thread_no  
    puts "In thread no." + thread_no.to_s
end

num_threads = 6
threads=[]

for thread_no in 1..num_threads
    puts "Creating thread no. "+thread_no.to_s
    threads << Thread.new{test(thread_no)}
end

threads.each { |thr| thr.join }

输出: 创建线程号1 创建线程号2 创建线程号3 创建线程号4 在线程号 4
创建线程号5 创建线程号6 在线程号 6
在线程号 6
在线程号 6
在线程号 6
在线程号 6

当然我想得到输出:在线程号中。 1 (2,3,4,5,6) 我能以某种方式实现这一点吗?

【问题讨论】:

  • 不知道 ruby​​,但应该应用与往常相同的解决方案:将局部变量 local_thread_no 用于 thread_no 传递给线程构造函数时

标签: ruby multithreading


【解决方案1】:

问题在于for-loop。在 Ruby 中,它重用了一个变量。 所以线程体的所有块都访问同一个变量。循环结束时 this 变量为 6。线程本身只能在循环结束后启动。

您可以使用each-loops 来解决这个问题。它们的实现更简洁,每个循环变量都独立存在。

(1..num_threads).each do | thread_no |
    puts "Creating thread no. "+thread_no.to_s
    threads << Thread.new{test(thread_no)}
end

不幸的是,ruby 中的for 循环是令人惊讶的来源。所以最好总是使用each 循环。

补充: 您还可以给Thread.new 一个或多个参数,这些参数会被传递到线程主体块中。通过这种方式,您可以确保该块在其自身范围之外不使用任何 var,因此它也适用于 for 循环。

threads <<  Thread.new(thread_no){|n| test(n) }

【讨论】:

    【解决方案2】:

    @Meier 已经提到了for-end 吐出与预期不同的结果的原因。

    for 循环是语言语法构造,它重用相同的局部变量 thread_nothread_no 产生 6,因为您的 for 循环在最后几个线程开始执行之前结束。

    为了摆脱此类问题,您可以将确切的thread_no 副本保留在另一个范围内 - 例如 -

    def test thread_no
      puts "In thread no." + thread_no.to_s
    end
    
    num_threads = 6
    threads     = []
    
    for thread_no in 1..num_threads
      threads << -> (thread_no) { Thread.new { test(thread_no) } }.  (thread_no)
    end
    
    threads.each { |thr| thr.join }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-09
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多