【问题标题】:Ruby threading pass control to mainRuby 线程将控制权传递给 main
【发布时间】:2010-10-29 10:05:41
【问题描述】:

我正在用 Ruby 编写一个应用程序,它为每个新工作创建一个新线程。所以这就像一个队列管理器,我在其中检查可以从数据库启动多少线程。现在当一个线程完成时,我想调用该方法来开始一个新工作(即一个新线程)。我不想创建嵌套线程,那么有没有办法加入/终止/退出调用线程并将控制权交给主线程?只是为了说明情况,此时可能还有其他线程在运行。

我尝试简单地加入调用线程,如果它不是主线程,我得到以下错误;

"thread 0x7f8cf8dcf438 tried to join itself"

任何建议都将受到高度赞赏。

提前致谢。

【问题讨论】:

  • 这是在重新发明轮子吗?您可以使用众多现有消息队列之一吗?

标签: ruby multithreading


【解决方案1】:

我会提出两种解决方案:

第一个是有效地加入线程,但必须从主线程调用连接(假设您从主线程启动了所有工作线程):

def thread_proc(s)
  sleep rand(5)
  puts "#{Thread.current.inspect}: #{s}"
end

strings = ["word", "test", "again", "value", "fox", "car"]

threads = []
2.times { 
  threads << Thread.new(strings.shift) { |s| thread_proc(s) }
}

while !threads.empty?
  threads.each { |t|
    t.join
    threads << Thread.new(strings.shift) { |s| thread_proc(s) } unless strings.empty?
    threads.delete(t)
  }
end

但这种方法效率有点低,因为一遍又一遍地创建线程会导致内存和 CPU 开销。

您应该更好地使用队列来同步一个固定的重用线程池:

require 'thread'

strings = ["word", "test", "again", "value", "fox", "car"]

q = Queue.new
strings.each { |s| q << s }

threads = []
2.times { threads << Thread.new {
  while !q.empty?
    s = q.pop
    sleep(rand(5))
    puts "#{Thread.current.inspect}: #{s}"
  end
}}

threads.each { |t| t.join }

【讨论】:

    【解决方案2】:
    t1 = Thread.new { Thread.current[:status] = "1"; sleep 10; Thread.pass; sleep 100 }  
    t2 = Thread.new { Thread.current[:status] = "2"; sleep 1000 }  
    t3 = Thread.new { Thread.current[:status] = "3"; sleep 1000 }  
    
    puts Thread.list.map {|X| x[:status] }
    #=> 1,2,3
    
    Thread.list.each do |x| 
      if x[:status] == 2 
        x.kill # kill the thread
        break
      end
    end  
    
    puts Thread.list.map {|X| x[:status] }
    #=> 1,3
    

    "Thread::pass" 将控制权交给调度器,调度器现在可以调度任何其他线程。线程已自愿放弃对调度程序的控制 - 我们无法指定将控制权传递给特定线程

    "Thread#kill" 将杀死线程实例

    "Thread::list" 将返回线程列表

    线程由调度程序管理,如果您想要显式控制,请检查纤程。但它有一些问题,JRuby 不支持纤维。

    还检查线程局部变量,它将帮助您传达线程的状态或返回值,而无需加入线程。

    http://github.com/defunkt/resque 是队列的不错选择,请查看。如果您要大量使用线程,也可以尝试 JRuby。它的优点是它将Java线程包装在红宝石中。

    【讨论】:

    • 我没有看到第一个答案(已经输入它然后出去喝咖啡)。但是看到它,线程池是生产质量代码的必备品。
    猜你喜欢
    • 1970-01-01
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-05
    • 2016-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多