新手问题 ruby 线程使用举例

fsword · 2013年02月06日 · 最后由 luotuo 回复于 2014年06月06日 · 8720 次阅读
本帖已被管理员设置为精华贴

这年头,大多数人应该不需要看这些内容了,所以以下也不是什么入门,只是有些同学还不太了解,举几个简单例子帮助理解

例子一:

require 'faraday'

Faraday.get 'http://www.sina.com'
puts 'web get done'
puts 'hello'

sleep 3
puts 'completed.'

很简单,ruby 脚本先下载,再依次打印 web get donehellocompleted.

例子二:

require 'faraday'

Thread.new do
  Faraday.get 'http://www.sina.com' 
  puts 'web get done'
end
puts 'hello'

sleep 3
puts 'completed.'

这次有所不同,下载和打印web get done的环节是和打印’completed.'同时发生的,这就是线程的作用——传递给 Thread.new 的 block 与后续代码”并行“执行了,我们也可以说,传入的 block 是异步执行(不会阻碍当前执行序列)

那如何拿到并行的执行结果呢?答案是等待。由于我们有 thread 对象,等待就是它的一个方法,比如这样:

require 'faraday'

t = Thread.new do
  Faraday.get 'http://www.sina.com' 
  puts 'web get done'
end
t.join
puts 'hello'

脚本执行到 thread 对象的 join 方法时,将会等待线程执行结束,然后继续进行。

传入线程的 block 也有返回值,所以我们还可以这样

require 'faraday'

t = Thread.new do
  Faraday.get 'http://www.sina.com' 
  'web get done'
end
puts 'hello'
puts t.value

与 join 类似,调用 thread 的 value 方法时,系统会等待线程执行结束,然后将 block 的执行结果返回

对新手很有用~~

那个这个线程会自动关闭么?还是说根本这个线程是“假”的

#2 楼 @guyanbiao 执行完了自然就结束(也就是你说的关闭),至于是真是假取决于你对”真“、”假“的定义,如果你指的是是否是操作系统分配的线程,那么不同的 ruby vm 各有不同,cruby 1.8 是”假“的,cruby1.9、jruby 是”真“的

有时困难的时不知到何时使用才是最佳实际哦

从来不用 join 的路过。。。

CRuby 1.9 线程是和操作系统线程一一对应的,也就是去掉了 GIL, 支持多线程了 但是还有 GVL, 线程虽然有了但还是在 VM 中最多只吃一个 CPU

GVL 和 GIL 的区别是,GVL 只要跑到 VM 外面 (例如 C 扩展), 两个线程是可以吃满两个 CPU 的

楼主举的例子不甚恰当,至少,对于了解多个线程是如何并行工作, 没有起到引导作用。

我这里提一下线程编程,个人总结的两点惯例...

  1. 在 t = Thread.new {...} 和 t.join 之间,通常会存在 同样费时 的逻辑代码。
  2. 因此,多数情况下,t.join , 写在调用代码的最后一行。

只要满足这两点,Thread 代码块中的代码,就可以和主线程中的代码 同时执行(具体是并发还是真并行,依赖于平台), 并且,主线程如果先完成,还会等待子线程也完成后,才会退出。

#7 楼 @zw963 是的,启动一个线程并 join 等同于顺序执行,如果是这样可能好理解一些

require 'faraday'

threads = %w{ sina sohu google }.map do |site|
  Thread.new do
    Faraday.get "http://www.#{site}.com"
    puts 'web get done'
  end
end
threads.map &:join
puts 'all page downloaded.'

join。value 没有其他?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号