参考手册:标准库——内部类

用来表示Ruby的线程的类。

Thread使得并行编程成为可能。线程是一种共享内存空间并可同时运行的控制流。但由于目前Ruby解释器采用时间片轮转法来控制线程,所以使用线程后并不会提高程序的运行速度。

启动程序时生成的线程被称作主线程。若主线程因为某些原因而终止运行时,其他的所有线程和整个程序也会终止运行。若因为用户的干预而引发了某些异常时,它们会被送往主线程。

若启动线程时指定的块结束运行时,该线程也将终结。块的终结包括正常结束和因异常等引起的非正常结束两种情况。

Ruby的线程调度工作采用的是带优先顺序的循环复用法。每隔一段时间或运行中的某线程主动弃权时,就会进行调度。此时将从可运行的线程中挑选一个优先度最高的线程,并将context交给它。

线程和异常

  若某线程内发生了异常,且没有被线程内的 rescue 捕捉到时,通常该线程会被停掉,而不会发出警告。但是,如果这时正好有其它线程因Thread#join而等待这个被停掉的线程时,则会在等待线程中再次引发相同的异常。

  begin
  t = Thread.new do
   Thread.pass  # 主线程确实是在等join
   raise "unhandled exception"
  end
  t.join
  rescue
  p $! # => "unhandled exception"
  end

  另外,下列方法可以保证在某线程因发生异常而终止工作时,整个解释器就会被中断。

   * 将内部变量$DEBUG的值设为真(调试模式)。另外,用-d选项来启动ruby解释器也可以取得相同的效果。
   * 使用Thread.abort_on_exception来设置标识。
   * 使用Thread#abort_on_exception来设定特定线程的标识。

  若使用了上述3个方法之一的话,整个解释器就会被中断。
线程的状态

  线程的运行状态如下。可以使用Object#inspect或Thread#status来查看线程的状态。

  p Thread.new {sleep 1} # => #<Thread:0xa039de0 sleep>

  run (运行 or 可运行状态)

   新生成的线程或那些被run以及wakeup方法唤醒的线程就是这种状态。有的线程会因为join而一直等待别的线程终止运行。而一旦这些线程终止运行,那些一直处于等待状态的线程也会变成这种状态。

   处于该状态中的线程是“活”的。
  sleep (挂起状态)

   那些被Thread.stop 和 join 方法挂起的线程就是这种状态。

   处于该状态中的线程是“活”的。
  aborting (终止处理中)

   那些被kill等扼杀的线程会暂时变为这种状态。有时还会从该状态变为挂起状态(stop)。

   处于该状态中的线程仍然是“活”的。
  dead (终止状态)

   那些被kill等扼杀的线程就会变为这种状态。若处于该状态中的线程已经完全没用的话,就由GC将其清出内存。

   处于该状态中的线程是“死”的。

超类:

  * Object

类方法:

Thread.abort_on_exception
Thread.abort_on_exception = newstate

  若其值为真的话,一旦某线程因异常而终止时,整个解释器就会被中断。它的默认值是假,也就是说,在通常情况下,若某线程发生异常且该异常未被Thread#join等检测到时,该线程会被无警告地终止。详情请参考线程和异常。

  它返回布尔值。在赋值形式中,它返回右边的newstate。
Thread.critical
Thread.critical = newstate

  当其值为真时,将不会进行线程切换。若当前线程挂起(stop)或有信号(signal)干预时,其值将自动变为false。

  但是,当使用Thread.new生成新线程时,新线程将被执行。另外,还可以使用Thread.pass进行显式地切换。

  它返回布尔值。在赋值形式中,它返回右边的newstate。

  注意: 若涉及到I/O,GC或扩展库的问题时,该标识可能会被忽视.若想进行互斥操作的话,不要使用该方法,而应该使用Mutex或Monitor.
Thread.current

  返回当前运行中的线程(当前线程)。
Thread.exit

  终止当前线程的运行。

  返回当前线程。

  若当前线程是唯一的一个线程时,将使用exit(0)来终止它的运行。
Thread.kill(thread)

  终止指定线程的运行。若该线程已经终止,则不作任何动作。

  返回thread。
Thread.list

  返回处于运行状态或挂起状态的活线程的数组。
Thread.main

  返回主线程。
Thread.new([arg, ...]) { ... }
Thread.start([arg, ...]) { ... }
Thread.fork([arg, ...]) { ... }

  生成线程,并开始对块进行计算.

  参数会被原封不动地传递给块. 这就可以在启动线程的同时,将值传递给该线程所固有的局部变量.

  返回生成的线程.

  例如,以下代码是错误的. 因为在线程开始运行之前, 变量i可能会被改写.

  for i in 1..5
   Thread.start { p i }
  end

  上面的代码应该改写为

  for i in 1..5
   Thread.start(i) {|t| p t }
  end

Thread.pass

  将运行权交给其他线程. 它不会改变运行中的线程的状态,而是将控制权交给其他可运行的线程(显式的线程调度).

  返回nil.
Thread.stop

  将当前线程挂起,直到其他线程使用run方法再次唤醒该线程.

  返回nil.

方法:

self[name]

  取出线程内与name相对应的固有数据. name可以是字符串或Symbol.

  若没有与name相对应的数据时, 返回nil.
self[name] = val

  将线程内与name相对应的固有数据的值设为val。 name可以是字符串或Symbol. 若将val设为nil时, 将删除该线程内的对应数据.

  返回val.
abort_on_exception
abort_on_exception = newstate

  它返回布尔值。在赋值形式中,它返回右边的newstate。

  若其值为真的话,一旦某线程因异常而终止时,整个解释器就会被中断。它的默认值是假.详情请参考线程和异常.
alive?

  若线程是"活"的,就返回true.

  如果Thread#status返回真的话,该方法也返回真.
exit
kill
terminate ((<ruby 1.7 特性>))

  终止线程的运行.

  返回self.
group ((<ruby 1.8 特性>))

  返回线程所属的ThreadGroup对象.

  p Thread.current.group == ThreadGroup:efault
  # => true

  死线程返回 nil .
join
join(limit) ((<ruby 1.7 特性>))

  挂起当前线程,直到self线程终止运行为止. 若self因异常而终止时, 将会当前线程引发同样的异常.

  返回self.

  ruby 1.7 特性: 若使用了limit参数的话, limit秒之后将会超时,并返回nil.

  下例中,将等待所有新生成的线程终止运行.

  threads = []
  threads.push(Thread.new { n = rand(5); sleep n; n })
  threads.push(Thread.new { n = rand(5); sleep n; n })
  threads.push(Thread.new { n = rand(5); sleep n; n })

  threads.each {|t| t.join}

key?(name)

  若与name相对应的线程固有数据已经被定义的话,就返回true. name可以是字符串或Symbol.
keys ((<ruby 1.7 特性>))

  以数组的形式返回与线程固有数据取得关联的索引. 它以Symbol的形式返回索引.

  th = Thread.current
  th[:foo] = 'FOO'
  th['bar'] = 'BAR'
  p th.keys

  #=> [:bar, :foo]

priority

  返回线程的优先度. 优先度的默认值为0. 该值越大则优先度越高.
priority = val

  设定线程的优先度. 也可以将其设定为负数.

  返回val.
raise([error_type,][message][,traceback])

  在该线程内强行引发异常.

  请参考内部函数raise来了解各参数的细节.

  Thread.new {
  sleep 1
  Thread.main.raise "foobar"
  }

  begin
  sleep
  rescue
  p $!, $@
  end

  => #<RuntimeError: foobar>
   ["-:3"]

run

  重新启动被挂起(stop)的线程. 与Thread#wakeup不同的是,它将立即进行线程的切换. 若对死进程使用该方法时, 将引发ThreadError异常.

  返回self.
safe_level

  返回self 的安全等级. 当前线程的safe_level与$SAFE相同.

  请参考安全模型来详细了解安全等级的相关内容.
status

  使用字符串"run"、"sleep"或"aborting" 来表示活线程的状态. 若某线程是正常终止的话,就返回false. 若因异常而终止的话,就返回nil.

  若Thread#alive?返回真的话,该方法也返回真.
stop?

  若线程处于终止状态(dead)或被挂起(stop)时,返回true.
value

  一直等到self线程终止运行(等同于join)后,返回该线程的块的返回值. 若在线程的运行过程中发生了异常, 就会再次引发该异常.

  在下例中, 将会等待所有新生成的线程都终止运行后再输出结果.

  threads = []
  threads.push(Thread.new { n = rand(5); sleep n; n })
  threads.push(Thread.new { n = rand(5); sleep n; n })
  threads.push(Thread.new { n = rand(5); sleep n; n })

  threads.each {|t| p t.value}

  若您觉得最后一行很难理解的话,可以写成这样.

  threads.each {|t| p t.join.value}

wakeup

  把被挂起(stop)的线程的状态改为可执行状态(run). 若对死线程执行该方法时,将会引发ThreadError异常.

  返回self。
Thread必然归属于某一个线程组. 可以使用ThreadGroup类来统一管理该线程组内的Thread.

默认的ThreadGroup是ThreadGroup::Default. 新生成的Thread归属于生成它的那个Thread所在的线程组.

例:

  等待所有新生成的线程终止运行

  5.times {
   Thread.new { sleep 1; puts "#{Thread.current} finished" }
  }

  (ThreadGroup::Default.list - [Thread.current]).each {|th| th.join}

  puts "all threads finished"

  若对象Thread可能会唤醒Thread时(请参考Thread.exclusive)

  Thread.exclusive do
  (ThreadGroup::Default.list - [Thread.current]).each {|th| th.join}
  end

超类:

  * Object

类方法:

ThreadGroup.new

  生成并返回一个新的ThreadGroup.

方法:

add(thread)

  将thread线程的线程组变为self.

  返回self.
enclose ((<ruby 1.8 特性>))

禁止向ThreadGroup中添加/删除Thread(但不会进行冻结).
(若添加/删除的话,则会引发((<ThreadError>))异常)

返回self.

添加的例子:

  thg = ThreadGroup.new.enclose
  thg.add Thread.new {}

  => -:2:in `add': can't move to the enclosed thread group (ThreadError)

删除的例子:

  thg1 = ThreadGroup.new
  thg2 = ThreadGroup.new

  th = Thread.new {sleep 1}

  thg1.add th
  thg1.enclose
  thg2.add th

  => -:8:in `add': can't move from the enclosed thread group (ThreadError)

enclosed? ((<ruby 1.8 特性>))

  以布尔值的形式返回enclose的状态.不能向被freeze的ThreadGroup中添加/删除Thread,此时enclosed?会返回false.

  thg = ThreadGroup.new
  p thg.enclosed?   # => false
  thg.enclose
  p thg.enclosed?   # => true

  thg = ThreadGroup.new
  p thg.enclosed?   # => false
  thg.freeze
  p thg.enclosed?   # => false

list

  以数组的形式返回self中的线程列表.

  返回结果中不会包括处于终结处理中(aborting)或终止状态(dead)的线程(这与Thread.list是一样的).

常数:

Default

  默认的ThreadGroup. 主线程最初就属于该线程组.
时间对象. Time.now返回当前时间. 由File#stat所返回的文件的时间标记正是Time对象.

Time对象中保存的是自起算时间以来所经过的秒数. 起算时间定在协调世界时(UTC,或旧称GMT)的1970年1月1日上午0点. 另外,是否计算闰秒要看系统而定.

现在Unix系统的最大时间是协调世界时2038年1月19日上午3点14分7秒.

另外,系统内部保存了一个标识,用来确定Time对象是采用协调世界时的时区还是采用地方时的时区的问题. 但是,该信息并未保存在Marshal.dump中.用Marshal.load读入的Time对象通常采用的是地方时的时区.

p Marshal.load(Marshal.dump(Time.now.gmtime)).zone
# => "JST"

ruby 1.9 特性: 自1.9开始, 时区标识符将被保存在Marshal数据之中.

p Marshal.load(Marshal.dump(Time.now.gmtime)).zone
# => "UTC"

超类:

  * Object

包含的模块:

  * Comparable

类方法:

Time.at(time[, usec])

  返回time所指时间的Time对象. time可以是Time对象,也可以是表示自起算时间以来的秒数的整数或浮点数.

  若浮点精度不够时,可以使用usec. 它将返回time + (usec/1000000)所表示的时间. 此时,time和usec都必需是整数.

  生成的Time对象将使用地方时的时区.
Time.gm(year[, mon[, day[, hour[, min[, sec[, usec]]]]]])
Time.gm(sec, min, hour, mday, mon, year, wday, yday, isdst, zone)
Time.utc(year[, mon[, day[, hour[, min[, sec[, usec]]]]]])
Time.utc(sec, min, hour, mday, mon, year, wday, yday, isdst, zone)

  返回由参数指定的协调世界时的Time对象. 第1参数后面的全是可选参数. 若省略这些参数的话,将使用最小的可能值.

  这些参数也可以处理字符串.

  p Time.gm *"2002-03-17".split("-")
  # => Sun Mar 17 00:00:00 UTC 2002

  mon是从1(1月)到12(12月)之间的整数或字符串. 还可以使用英语的月份名("Jan", "Feb", ... 等简称. 大小写均可).

  若参数的个数与Time#to_a完全相同(此时,秒将出现在头部)时,可对其进行正确解读. 若使用这种形式来传递参数的话, wday, yday和zone这些参数的值将被忽略. 另外,应该使用布尔值来指定是否在isdst中使用夏令时(Daylight Saving Time (Summer Time)).
Time.local(year[, mon[, day[, hour[, min[, sec[, usec]]]]]])
Time.local(sec, min, hour, mday, mon, year, wday, yday, isdst, zone)
Time.mktime(year[, mon[, day[, hour[, min[, sec[, usec]]]]]])
Time.mktime(sec, min, hour, mday, mon, year, wday, yday, isdst, zone)

  返回由参数指定的地方时的Time对象. 参数的处理方式与Time.gm相同.
Time.new
Time.now

  返回当前时间的Time对象. new与now的区别在于,它会调用initialize.
Time.times ((<obsolete>))

  以Struct::Tms的形式返回自身进程和其子进程所消耗的用户/系统CPU时间情况. Struct::Tms是结构体类,它有下列成员.

  utime    # user time
  stime    # system time
  cutime    # user time of children
  cstime    # system time of children

  采用浮点数的形式来表示时间,其单位为秒. 详情请参考time(3).

  ruby 1.7 特性 该方法被转移到Process中. 您仍然可以使用Time.times,但会出现警告信息.

方法:

self + other

  返回self之后other秒钟的那个时间.
self - other

  若other是Time对象的话,就以Float形式返回这二者间的时间差,单位是秒. 若other是数值时, 就返回self之前other秒钟的那个时间.
self <=> other

  时间的比较. other必需是Time对象或数值.若是数值的话, 就把它当做自起算时间以来经过的秒数,然后进行比较.
asctime
ctime

  将时间变为asctime(3)形式的字符串. 但不包含末尾的 \n .
gmt?
utc?

  若self的时区是协调世界时的话,就返回真.
getgm
getutc

  ruby 1.7 特性

  新生成并返回一个时区设为协调世界时的Time对象.
getlocal

  ruby 1.7 特性

  新生成并返回一个时区设为地方时的Time对象.
gmtime
utc

  将时区设为协调世界时.返回self.

  调用该方法之后, 将以协调世界时的方式来处理时间变换的问题. 若想显示协调世界时的话,可以这样.

  print Time.now.gmtime, "\n"

  localtime和gmtime的运作情况要取决于系统中localtime(3). 虽说Time类中保存的是自起算时间以来经过的秒数, 但针对某特定的时刻来计算经过秒数时,还是会出现差异,这是因为有的系统会计算闰秒,有的则不计算. 因此,跨平台交接Time对象时,要特别注意这个问题.
localtime

  将时区设为地方时(默认). 返回self.

  调用该方法之后, 将以协调地方时的方式来处理时间变换的问题.

  localtime和gmtime的运作情况要取决于系统中localtime(3). 虽说Time类中保存的是自起算时间以来经过的秒数, 但针对某特定的时刻来计算经过秒数时,还是会出现差异,这是因为有的系统会计算闰秒,有的则不计算. 因此,跨平台交接Time对象时,要特别注意这个问题.
strftime(format)

  按照format字符串的模式,将时间变为字符串,并返回结果. format字符串可以使用下列形式.

   * %A: 星期几的名称(Sunday, Monday ... )
   * %a: 星期几的简称(Sun, Mon ... )
   * %B: 月份的名称(January, February ... )
   * %b: 月份的简称(Jan, Feb ... )
   * %c: 日期和时间
   * %d: 日期(01-31)
   * %H: 24时制的小时(00-23)
   * %I: 12时制的小时(01-12)
   * %j: 一年中的第几天(001-366)
   * %M: 分钟(00-59)
   * %m: 表示月份的数字(01-12)
   * %p: 上午/下午(AM,PM)
   * %S: 秒钟(00-60) (60是闰秒)
   * %U: 表示周的数字.以第一个星期天作为第一周的开始(00-53)
   * %W: 表示周的数字.以第一个星期一作为第一周的开始(00-53)
   * %w: 表示星期几的数字. 星期天是0(0-6)
   * %X: 时刻
   * %x: 日期
   * %Y: 表示公历年份的数字
   * %y: 公历年份的后两位数字(00-99)
   * %Z: 时区trap
   * %%: %本身

  目前,该方法会原封不动地调用系统的strftime(3). 所以,有时可以使用一些其他的format形式.但是这会降低移植性,请充分留意.
sec
min
hour
mday
day (mday 的别名)
mon
month (mon 的别名)
year
wday
yday
isdst
dst? (isdst 的别名)
zone

  返回时间的要素.

   * hour, min, sec: 以整数形式返回时、分、秒.
   * year, month(mon), day(mday): 以整数形式返回年、月、日.
   * wday: 以0(星期日)到6(星期六)之间的整数返回星期几.
   * yday: 以整数(1到366)的形式返回某天是一年中的第几天,以1月1日作为第1天.
   * isdst(dst?): 若为夏令时就返回 true,否则返回 false.
   * zone: 返回表示时区的字符串.

  请参考localtime(3).

  注意: 与C语言的tm结构体不同的是, 如果是1月份,month就返回1; 如果是1998年,year就返回1998. 另外,yday从1算起.
succ ((<ruby 1.8 特性>))

  将self加上1秒钟以后生成并返回一个Time对象. 时区采用地方时.

  t = Time.now
  p t
  p t.succ
  # => Sun Jul 18 01:41:22 JST 2004
   Sun Jul 18 01:41:23 JST 2004

utc_offset
gmt_offset
gmtoff

  返回一个以秒为单位的数值, 该数值显示了与协调世界时之间的时差.

  若地方时走得比协调世界时快时(亚洲,澳大利亚等),返回一个正值;若慢时(美国等),就返回一个负值.

  p Time::now.zone # => "JST"
  p Time::now.utc_offset
  # => 32400

  若已将时区设为协调世界时的话,就返回0.

  p Time::now.zone # => "JST"
  p Time::now.getgm.utc_offset
  # => 0

  该方法是在Ruby 1.6.7版本中引进的.
to_a

  以一个包括10个元素的数组的形式返回某时间. 数组元素的排列如下.

   * sec: 秒 (整数 0-60)
   * min: 分 (整数 0-60)
   * hour: 时 (整数 1-24)
   * mday: 日 (整数)
   * mon: 月 (整数 1-12)
   * year: 年 (整数 2000钳=2000)
   * wday: 星期几 (整数 0-6)
   * yday: 一年的第几天 (整数 1-366)
   * isdst: 有无夏令时 (true/false)
   *

    zone: 时区 (字符串)

    p Time.now  # => Mon Oct 20 06:02:10 JST 2003
    p Time.now.to_a # => [10, 2, 6, 20, 10, 2003, 1, 293, false, "JST"]

  元素顺序与C语言的tm结构体相同. 但是tm结构体中没有 zone.

  注意: 与C语言的tm结构体不同的是, 如果是1月份,month就返回1; 如果是1998年,year就返回1998. 另外,yday从1算起.
to_f

  以浮点数形式返回自起算时间以来经过的秒数. 它可以表示那些非整秒的情况.
to_i
tv_sec

  以整数形式返回自起算时间以来经过的秒数.
to_s

  将某时刻变换为形如date(1)形式的字符串. 它等同于

  self.strftime("%a %b %d %H:%M:%S %Z %Y")

  这样.

  p Time.now.to_s # => "Mon Oct 20 06:02:10 JST 2003"

usec
tv_usec

  返回某时刻的微秒部分.
true的类. true是TrueClass类的唯一的实例. true只是那些表示真的对象中的一个代表.
超类:

  * Object

方法:

self & other

  若other为真则返回true,为假则返回false.
self | other

  总是返回true.
self ^ other

  若other为真则返回false,为假则返回true.
未绑定receiver的方法对象的类。它由Module#instance_method、Method#unbind等生成,在使用UnboundMethod#bind获取receiver以后就可以生成Method对象。

例: 我们可以用UnboundMethod来重写Method 类的开篇例程

class Foo
 def foo() "foo" end
 def bar() "bar" end
 def baz() "baz" end
end

# 将索引和方法的对应关系存入哈希表
# 请注意,这里并不包含receiver的信息
methods = {1 => Foo.instance_method(:foo),
    2 => Foo.instance_method(:bar),
    3 => Foo.instance_method(:baz)}

# 使用索引来调用相关方法
# receiver为任意对象(但必须是Foo 类的实例)
p methods[1].bind(Foo.new).call  # => "foo"
p methods[2].bind(Foo.new).call  # => "bar"
p methods[3].bind(Foo.new).call  # => "baz"

例: 使用UnboundMethod来重定义方法(通常情况下使用alias、super等)

class Foo
 def foo
  p :foo
 end
 @@orig_foo = instance_method :foo
 def foo
  p :bar
  @@orig_foo.bind(self).call
 end
end

Foo.new.foo

=> :bar
 :foo

超类:

  * Method version 1.6 以前
  * Object (version 1.8 以后)

方法:

self[args, ...]
call(args, ...)
call(args, ...) { ... }

  如果UnboundMethod尚未bind的话,将无法调用。通常会引发TypeError异常。

  class Foo
  def foo
  end
  end
  Foo.instance_method(:foo).call

  # => -:5:in `call': you cannot call unbound method; bind first (TypeError)

  ruby 1.8 特性:该方法被取消。
bind(obj)

  将self绑定到obj上生成并返回一个bound method对象(即Method对象)。只能对下列两种对象进行绑定:调用过unbind方法的对象的类的实例;内部包含(定义某方法的)模块的类的实例。除此以外将引发TypeError异常。

  例:

  # 类的实例方法的UnboundMethod

  class Foo
  def foo
   "foo"
  end
  end

  # 生成UnboundMethod `m'
  p m = Foo.instance_method(:foo) # => #<UnboundMethod: Foo(Foo)#foo>

  # 生成Method对象,它以Foo的实例为receiver
  p m.bind(Foo.new)     # => #<Method: Foo(Foo)#foo>

  # 生成Method对象,它以Foo的Bar子类
  # 的实例为receiver(被禁止)
  # ruby 1.8 特性: 取消了该限制

  class Bar < Foo
  end
  # p m.bind(Bar.new)     # => -18:in `bind': bind argument must be an instance of Foo (TypeError)

  # 定义同名的特殊方法也不行
  class << obj = Foo.new
  def foo
  end
  end
  p m.bind(obj)       # => -:25:in `bind': method `foo' overridden (TypeError)

  # 模块的实例方法的UnboundMethod

  module Foo
  def foo
   "foo"
  end
  end

  # 生成UnboundMethod `m'
  p m = Foo.instance_method(:foo) # => #<UnboundMethod: Foo(Foo)#foo>

  # 生成Method对象,它以内部包含Foo的Bar类
  # 的实例为receiver
  class Bar
  include Foo
  end
  p m.bind(Bar.new)     # => #<Method: Bar(Foo)#foo>

  # Bar的子类也包含Foo,所以没问题
  class Baz <Bar
  end
  p m.bind(Baz.new)     # => #<Method: Baz(Foo)#foo>

  # 定义同名的特殊方法也不行
  class << obj = Baz.new
  def foo
  end
  end
  p m.bind(obj)       # => -:27:in `bind': method `foo' overridden (TypeError)

to_proc

  生成一个调用(call)self的Proc对象。
unbind

  返回self。

  ruby 1.8 特性:该方法已取消。
nil的类. 伪变量(的值)nil是NilClass类的唯一实例. nil和false对象都表示假. 其他所有的对象都表示真.
超类:

  * Object

方法:

self & other

  总是返回false.
self | other
self ^ other

  若other为真则返回 true, 为假则返回false.
nil?

  总是返回true.
to_a

  返回空数组[].
to_f ((<ruby 1.7 特性>))

  返回0.0。
to_i

  返回0。
to_s

  返回空字符串""。