红宝石 |线程生命周期及其状态
线程生命周期提供了线程从诞生到结束的简要描述。可以在Thread.new或Thread.start或Thread.fork方法的帮助下创建一个新线程。创建后无需启动新线程。当 CPU 资源可用时,线程会自动开始运行。 Thread.new引用的值是一个 Thread 对象。 Thread 类提供了多种查询和操作线程的方法。
线程运行到与调用Thread.new相关的代码块中,然后停止运行。线程块中最后一个表达式的值就是线程的值,通过调用Thread对象的value方法获取该值。 value 方法仅在线程完全运行时才返回值,否则它不会向完全运行的线程返回值。如果线程中引发异常,则终止正在运行的线程。这种情况只适用于那些不是主线程的线程,并且只有那些包含异常的线程才会终止。
线程状态
在 Ruby 中,线程有五种可用的状态来显示线程的状态。你可以通过使用alive来检查线程的状态吗?和状态方法。
- Runnable:当前正在运行或准备好在可用时占用 CPU 资源的线程。
- Sleeping:当前正在休眠的线程,或者正在等待 IO,或者自己停止的线程。
- Aborting:这是一个中间状态。已被杀死但尚未终止的中止线程。
- 异常终止:线程包含异常,或者换句话说,由于异常的出现而终止的线程。
- 正常终止:正常终止的线程,或者不包含异常并完成工作的线程。
例子:
# Ruby program to illustrate # check status of thread counter = 0 # creating new thread x = Thread.new { loop { counter += 1 } } # check thread alive or not puts x.alive?
输出:
true
下表显示了状态的名称及其返回值:
States | Return Value |
---|---|
Runnable | run |
Sleeping | sleep |
Aborting | aborting |
Terminated normally | false |
Terminated with exception | nil |
主线程
在 Ruby 中,主线程是多线程的一个特殊部分。它是一个程序的最顶层线程,所有子线程都在这个线程下运行,或者换句话说,它是父线程,同一个程序的其他线程是主线程的子线程。主线程是在main方法的帮助下创建的。当主线程的工作完成时,Ruby 解释器停止运行,这意味着主线程和子线程完成了各自的任务。类方法Thread.main返回代表主线程的 Thread 对象。如果在主线程中引发异常并且没有在任何地方处理,那么 Ruby 解释器会打印一条消息或退出。如果在主线程以外的线程中引发异常,则 Ruby 解释器终止包含异常的线程
例子:
# Ruby program to illustrate
# main thread
# Create main thread
puts Thread.main
puts ""
# create new thread
a1 = Thread.new {sleep 200}
list_thread= Thread.list
list_thread.each {|t| p t }
puts "Current thread = " + Thread.current.to_s
# create new thread
a2 = Thread.new {sleep 200}
list_thread= Thread.list
list_thread.each {|t| p t }
puts "Current thread=" + Thread.current.to_s
# kill thread a1
Thread.kill(a1)
# pass execution to thread a2
Thread.pass
# kill thread a2
Thread.kill(a2)
list_thread= Thread.list
list_thread.each {|t| p t }
# exit main thread
Thread.exit
输出:
#
#
#
Current thread = #
#
#
#
Current thread=#
#
#
说明:这个程序显示了主线程是如何执行的。首先,我们创建主线程,然后在这个主线程中有两个子线程,即a1和a2线程。当线程a1完全执行时,然后终止a1线程并将执行传递给a2线程。之后杀死a2线程并打印主线程中存在的线程列表及其状态。当主线程中存在的所有线程都死了,那么主线程就存在了。
备用线程状态:暂停、唤醒和终止
正如我们所知,线程是在可运行状态下创建并准备好运行的。线程通过进入睡眠状态、调用Thread.stop方法或调用Kernel.sleep来暂停自身。没有线程可以被另一个线程强行暂停。如果一个线程在没有参数的情况下调用Kernel.sleep ,那么它会永远暂停线程或直到被唤醒,如果一个线程用一个参数调用Kernel.sleep ,那么它会暂时将线程置于睡眠状态。当给定时间到期时,处于临时睡眠状态的线程会自动唤醒并重新进入可运行状态。
通过调用Thread.stop或调用kernel.sleep暂停的线程可以通过调用实例方法重新启动,即唤醒并运行。这些方法将线程的状态从睡眠切换到可运行。 run 方法还调用线程调度程序。由于线程调度器的调用,最近唤醒的线程可能会获得CPU资源。 wakeup 方法在不调用线程调度程序的情况下唤醒特定线程。
一个线程可以通过调用实例方法kill来强制终止其他线程。终止和退出方法类似于 kill 方法。这些方法将被杀死的方法置于正常终止状态。除非您有办法知道线程未处于文件共享状态的中间,否则终止线程是危险的事情。用 ! 杀死一个线程方法更有害,因为被杀死的线程可能会使套接字、文件和其他资源保持打开状态。