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
(唉目前没有选择改变它)
经过一些阅读和一些试验和错误,我已经找到了以下解决方案.发布在这里,以防它帮助他人.
您可以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 实际的文档描述了一种不同的方法,但实际的代码不同意文档,所以我在这里介绍的代码是基于实际工作的.