當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


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類。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。