Ruby一次只创建3个线程

时间:2009-02-14 04:11:24

标签: ruby multithreading

我正在尝试运行500个客户端,这些客户端同时向服务器发送一些请求以进行负载测试。客户端再次成为ruby程序。听起来微不足道。但是我遇到了ruby线程的奇怪问题。我的代码看起来像这样 -

n = 10

n.times do
  Thread.new do
    `calc`
  end
end

代码是一个示例。我只是试图从命令行运行calc命令(如果您在Windows以外的平台上尝试此代码,请将其替换为适用于您的命令行或shell的命令)。稍后将替换为“ruby my_client.rb”,并且n的值将设置为500(或其他)。

我在这里遇到的问题是,无论我想创建多少个线程,一次只能创建 3 个线程。那只是同时打开3个计算窗口。剩余的线程只是在队列中等待等待这3个线程的终止。可能与阻止和非阻塞调用有关。但是我尝试了Java相同的程序,它运行得很好。这是一句老话,不建议使用红宝石线。这是Ruby的线程存在问题还是我做错了?

4 个答案:

答案 0 :(得分:4)

您正在观察的问题特定于GUI应用程序。当你在worker中运行命令行时,它会变得更好。

通过下面的示例,我可以很好地运行200个wget实例,这可能足以满足您的负载测试目标。

n = 200

threads = []
(1..n).each do |i|
  threads << Thread.new do
    puts `wget google.com` # forgive me google
    sleep 10
    puts "#{i} done"
  end
end

threads.each do |t| # wait until all workers are done
  t.join
end

如果从wget切换到用于获取网页的Ruby代码,则可能会获得更多工作者。而且,你应该记住,Ruby线程只能扩展到那么远。不要指望有数千个或并行线程可以正常工作 - 尝试使用子进程或基于延续的方法。

答案 1 :(得分:3)

Ruby(MRI)的“Matz”C实现不使用1.8.6的本机线程。我相信这在Ruby 1.9中有所改变,但据我所知,由于Global Interpreter Lock,我们可能仍然不会看到出色的多线程性能。

如果您确实需要良好的多线程支持,并且您的软件可以用Ruby编写,那么您可以尝试在JRuby上运行它。一个快速的健全性测试表明,使用你的例子我将在MRI上获得2个OS线程,在JRuby下运行相同的东西时获得12个。这是在OS X上使用“MRI”1.8.6和JRuby 1.1.6。

另一种选择,因为看起来你要生成一个线程来分叉一个新进程,可能会改为使用DRb。

答案 2 :(得分:0)

这对我来说非常适合我与osx一起使用。

n = 10

threads = []
n.times do |i|
  threads << Thread.new do
    `mate test#{i}.txt`
  end
end

threads.each { |t| t.join }

答案 3 :(得分:0)

您可能希望生成单独的进程。 Kernel::fork在Windows下不起作用,因此您必须使用旧的Kernel::systemKernel::popen并为其创建单独的脚本或使用特殊的命令行参数。

虽然Ruby 1.9几乎就在那里,如果你可以打开它,它确实有本机操作系统线程,那样的东西就不会发生。