我应该如何使用Concurrent-Ruby限制线程创建?

Dav*_*Sag 1 ruby concurrency multithreading concurrent-ruby

我有一个进程,它使用concurrent-ruby gem来同时处理大量的API调用Concurrent::Future.execute,并且在一段时间后它会死掉:

ERROR -- : can't create Thread (11) (ThreadError)
/current/vendor/bundler_gems/ruby/2.0.0/bundler/gems/concurrent-ruby-cba3702c4e1e/lib/concurrent/executor/ruby_thread_pool_executor.rb:280:in `initialize'
Run Code Online (Sandbox Code Playgroud)

有没有一种简单的方法可以告诉Concurrent它限制它产生的线程数,因为我无法预先知道它需要进行多少次API调用?

或者这是我需要在我的应用程序中明确编码的东西?

我正在使用Ruby 2.0.0(唉目前没有选择改变它)

Dav*_*Sag 5

经过一些阅读和一些试验和错误,我已经找到了以下解决方案.发布在这里,以防它帮助他人.

您可以Concurrent通过指定1来控制使用线程的方式RubyThreadPoolExecutor

所以,在我的情况下代码看起来像:

threadPool = Concurrent::ThreadPoolExecutor.new(
  min_threads: [2, Concurrent.processor_count].min,
  max_threads: [2, Concurrent.processor_count].max,
  max_queue:   [2, Concurrent.processor_count].max * 5,
  overflow_policy: :caller_runs
)

result_things = massive_list_of_things.map do |thing|
  (Concurrent::Future.new executor: threadPool do
    expensive_api_call using: thing
  end).execute
end
Run Code Online (Sandbox Code Playgroud)

所以在我的笔记本电脑上我有4个处理器,所以这样它将使用2到4个线程,并允许队列中最多20个线程,然后强制执行使用调用线程.随着线程释放,并发库将重新分配它们.

选择正确的max_queue值乘数似乎是一个试验和错误的问题; 但这5是一个合理的猜测.

1 实际的文档描述了一种不同的方法,但实际的代码不同意文档,所以我在这里介绍的代码是基于实际工作的.