【问题标题】:Limiting concurrent threads限制并发线程
【发布时间】:2011-09-14 19:25:50
【问题描述】:

我在通过 sftp 上传文件的程序中使用线程。可以上传的文件数量可能非常大或非常小。我希望能够同时上传 5 个或更少,如果还有更多,让他们等待。我的理解通常是一个条件变量将用于此,但在我看来,这一次只允许 1 个线程。

cv = ConditionVariable.new

t2 = Thread.new {
  mutex.synchronize {
    cv.wait(mutex)
    upload(file)
    cv.signal
  }
}

我认为这应该告诉它等待 cv 可用,然后在完成后发布它。我的问题是如何在限制数量的同时一次允许超过 1 个?

编辑:我在 Windows 上通过一键安装程序使用 Ruby 1.8.7

【问题讨论】:

  • 您使用的 Ruby 版本对于这个问题很重要。

标签: ruby multithreading


【解决方案1】:

改用线程池。请参阅Deadlock in ThreadPool(具体为接受的答案)。

【讨论】:

    【解决方案2】:

    请注意——除非您使用 JRuby,否则 Ruby 中没有真正的并发性。此外,除非您处于调试模式,否则线程中的异常将冻结主循环。

    require "thread"
    
    POOL_SIZE = 5
    
    items_to_process = (0..100).to_a
    
    message_queue = Queue.new
    
    start_thread = 
      lambda do
        Thread.new(items_to_process.shift) do |i|
          puts "Processing #{i}"
          message_queue.push(:done)
        end
      end
    
    items_left = items_to_process.length
    
    [items_left, POOL_SIZE].min.times do
      start_thread[]
    end
    
    while items_left > 0 
      message_queue.pop
      items_left -= 1
      start_thread[] unless items_left < POOL_SIZE
    end
    

    【讨论】:

    • 这不是真的。 MRI 1.9.2 版使用带有 GIL 的本机/内核线程。它不如 JRuby 或 MacRuby 线程有效,但它们不是 1.8.7 所拥有的绿色线程。在做 IO 工作的情况下(就像问题暗示的那样)1.9.2 线程非常有用(如果你不相信我,看看 Typhoeus)。
    • @coreyward 同意。我一直认为即使在 1.8.7 中 IO 实际上也是并行完成的。很难相信 Ruby 使用阻塞调用来冻结调度程序的 IO 系统。此外,线程池可用于限制套接字使用、文件句柄等。
    猜你喜欢
    • 1970-01-01
    • 2015-07-17
    • 2013-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多