本文简要介绍ruby语言中 Thread类
的用法。
线程是并发编程模型的 Ruby 实现。
需要多个执行线程的程序非常适合 Ruby 的 Thread
类。
例如,我们可以使用 ::new
创建一个独立于主线程执行的新线程。
thr = Thread.new { puts "What's the big deal" }
然后我们可以暂停主线程的执行并允许我们的新线程完成,使用 join
:
thr.join #=> "What's the big deal"
如果我们在主线程终止之前不调用thr.join
,那么包括thr
在内的所有其他线程都将被杀死。
或者,您可以使用数组同时处理多个线程,如下例所示:
threads = []
threads << Thread.new { puts "What's the big deal" }
threads << Thread.new { 3.times { puts "Threads are fun!" } }
创建几个线程后,我们等待它们全部连续完成。
threads.each { |thr| thr.join }
要检索线程的最后一个值,请使用 value
thr = Thread.new { sleep 1; "Useful value" }
thr.value #=> "Useful value"
Thread
初始化
为了创建新线程,Ruby 提供了 ::new
、 ::start
和 ::fork
。必须为这些方法中的每一个提供一个块,否则将引发 ThreadError
。
当子类化 Thread
类时,您的子类的 initialize
方法将被 ::start
和 ::fork
忽略。否则,请务必在 initialize
方法中调用 super。
Thread
终止
对于终止线程,Ruby 提供了多种方法来执行此操作。
类方法 ::kill
旨在退出给定线程:
thr = Thread.new { sleep }
Thread.kill(thr) # sends exit() to thr
或者,您可以使用实例方法 exit
或其任何别名 kill
或 terminate
。
thr.exit
Thread
状态
Ruby 提供了一些实例方法来查询给定线程的状态。要获取具有当前线程状态的字符串,请使用 status
thr = Thread.new { sleep }
thr.status # => "sleep"
thr.exit
thr.status # => false
您还可以使用 alive?
来判断线程是在运行还是在休眠,并使用 stop?
来判断线程是死了还是休眠。
Thread
变量和范围
由于线程是使用块创建的,因此相同的规则适用于变量范围的其他 Ruby 块。在这个块中创建的任何局部变量只能由这个线程访问。
Fiber-local 与线程本地
每根光纤都有自己的存储桶用于 Thread#[]
存储。当您设置新的 fiber-local 时,它只能在此 Fiber
中访问。为了显示:
Thread.new {
Thread.current[:foo] = "bar"
Fiber.new {
p Thread.current[:foo] # => nil
}.resume
}.join
此示例使用 []
获取和 []=
设置fiber-locals,您还可以使用 keys
列出给定线程的fiber-locals,并使用 key?
检查是否存在fiber-local。
对于thread-locals,它们可以在线程的整个范围内访问。给定以下示例:
Thread.new{
Thread.current.thread_variable_set(:foo, 1)
p Thread.current.thread_variable_get(:foo) # => 1
Fiber.new{
Thread.current.thread_variable_set(:foo, 2)
p Thread.current.thread_variable_get(:foo) # => 2
}.resume
p Thread.current.thread_variable_get(:foo) # => 2
}.join
您可以看到线程局部的:foo
转移到光纤中,并在线程结束时更改为2
。
此示例使用 thread_variable_set
来创建新的thread-locals,并使用 thread_variable_get
来引用它们。
还有 thread_variables
列出所有thread-locals,还有 thread_variable?
来检查给定的线程本地是否存在。
Exception
处理
当线程内部引发未处理的异常时,它将终止。默认情况下,此异常不会传播到其他线程。异常被存储,当另一个线程调用 value
或 join
时,异常将在该线程中重新引发。
t = Thread.new{ raise 'something went wrong' }
t.value #=> RuntimeError: something went wrong
可以使用 Thread#raise
实例方法从线程外部引发异常,该方法采用与 Kernel#raise
相同的参数。
设置 Thread.abort_on_exception
= true、 Thread#abort_on_exception
= true 或 $DEBUG = true 将导致线程中引发的后续未处理异常在主线程中自动重新引发。
通过添加类方法 ::handle_interrupt
,您现在可以使用线程异步处理异常。
调度
Ruby 提供了几种方法来支持程序中的调度线程。
第一种方法是使用类方法 ::stop
,使当前运行的线程进入休眠状态并安排另一个线程的执行。
一旦线程休眠,您可以使用实例方法 wakeup
将您的线程标记为符合调度条件。
您也可以尝试 ::pass
,它尝试将执行传递给另一个线程,但取决于操作系统是否正在运行的线程会切换。 priority
也是如此,它允许您向线程调度程序提示在传递执行时要优先处理哪些线程。此方法也取决于操作系统,在某些平台上可能会被忽略。
相关用法
- Ruby Thread.kill用法及代码示例
- Ruby Thread.pending_interrupt?用法及代码示例
- Ruby Thread kill()用法及代码示例
- Ruby Thread add_trace_func用法及代码示例
- Ruby ThreadError类用法及代码示例
- Ruby Thread.report_on_exception用法及代码示例
- Ruby Thread.group用法及代码示例
- Ruby Thread abort_on_exception用法及代码示例
- Ruby Thread terminate()用法及代码示例
- Ruby Thread.list用法及代码示例
- Ruby Thread.ignore_deadlock =用法及代码示例
- Ruby Thread.stop用法及代码示例
- Ruby Thread.abort_on_exception=用法及代码示例
- Ruby Thread.stop?用法及代码示例
- Ruby Thread.new用法及代码示例
- Ruby Thread.report_on_exception=用法及代码示例
- Ruby ThreadGroup.add用法及代码示例
- Ruby ThreadGroup.list用法及代码示例
- Ruby Thread.value用法及代码示例
- Ruby Thread.run用法及代码示例
- Ruby Thread exit()用法及代码示例
- Ruby Thread backtrace_locations()用法及代码示例
- Ruby Thread.thread_variables用法及代码示例
- Ruby Thread.thread_variable?用法及代码示例
- Ruby Thread.thr[sym]用法及代码示例
注:本文由纯净天空筛选整理自ruby-lang.org大神的英文原创作品 Thread类。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。