当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


Ruby Thread类用法及代码示例


本文简要介绍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-lang.org大神的英文原创作品 Thread类。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。